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 #[cfg(feature = "unstable_session_system_prompt")]
1250 #[serde(default)]
1251 pub system_prompt: Option<SystemPrompt>,
1252 #[serde_as(deserialize_as = "DefaultOnError")]
1258 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1259 #[serde(default)]
1260 #[serde(rename = "_meta")]
1261 pub meta: Option<Meta>,
1262}
1263
1264impl NewSessionRequest {
1265 #[must_use]
1267 pub fn new(cwd: impl Into<PathBuf>) -> Self {
1268 Self {
1269 cwd: cwd.into(),
1270 additional_directories: vec![],
1271 mcp_servers: vec![],
1272 #[cfg(feature = "unstable_session_system_prompt")]
1273 system_prompt: None,
1274 meta: None,
1275 }
1276 }
1277
1278 #[must_use]
1280 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1281 self.additional_directories = additional_directories;
1282 self
1283 }
1284
1285 #[must_use]
1287 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1288 self.mcp_servers = mcp_servers;
1289 self
1290 }
1291
1292 #[cfg(feature = "unstable_session_system_prompt")]
1298 #[must_use]
1299 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1300 self.system_prompt = system_prompt.into_option();
1301 self
1302 }
1303
1304 #[must_use]
1310 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1311 self.meta = meta.into_option();
1312 self
1313 }
1314}
1315
1316#[serde_as]
1320#[skip_serializing_none]
1321#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1322#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1323#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
1324#[serde(rename_all = "camelCase")]
1325#[non_exhaustive]
1326pub struct NewSessionResponse {
1327 pub session_id: SessionId,
1331 #[serde_as(deserialize_as = "DefaultOnError")]
1335 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1336 #[serde(default)]
1337 pub modes: Option<SessionModeState>,
1338 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1340 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1341 #[serde(default)]
1342 pub config_options: Option<Vec<SessionConfigOption>>,
1343 #[serde_as(deserialize_as = "DefaultOnError")]
1349 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1350 #[serde(default)]
1351 #[serde(rename = "_meta")]
1352 pub meta: Option<Meta>,
1353}
1354
1355impl NewSessionResponse {
1356 #[must_use]
1358 pub fn new(session_id: impl Into<SessionId>) -> Self {
1359 Self {
1360 session_id: session_id.into(),
1361 modes: None,
1362 config_options: None,
1363 meta: None,
1364 }
1365 }
1366
1367 #[must_use]
1371 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1372 self.modes = modes.into_option();
1373 self
1374 }
1375
1376 #[must_use]
1378 pub fn config_options(
1379 mut self,
1380 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1381 ) -> Self {
1382 self.config_options = config_options.into_option();
1383 self
1384 }
1385
1386 #[must_use]
1392 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1393 self.meta = meta.into_option();
1394 self
1395 }
1396}
1397
1398#[serde_as]
1406#[skip_serializing_none]
1407#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1408#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1409#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1410#[serde(rename_all = "camelCase")]
1411#[non_exhaustive]
1412pub struct LoadSessionRequest {
1413 #[serde_as(deserialize_as = "DefaultOnNull")]
1415 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1416 pub mcp_servers: Vec<McpServer>,
1417 pub cwd: PathBuf,
1419 #[serde_as(deserialize_as = "DefaultOnNull")]
1426 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1427 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1428 pub additional_directories: Vec<PathBuf>,
1429 pub session_id: SessionId,
1431 #[cfg(feature = "unstable_session_system_prompt")]
1443 #[serde(default)]
1444 pub system_prompt: Option<SystemPrompt>,
1445 #[serde_as(deserialize_as = "DefaultOnError")]
1451 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1452 #[serde(default)]
1453 #[serde(rename = "_meta")]
1454 pub meta: Option<Meta>,
1455}
1456
1457impl LoadSessionRequest {
1458 #[must_use]
1460 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1461 Self {
1462 mcp_servers: vec![],
1463 cwd: cwd.into(),
1464 additional_directories: vec![],
1465 session_id: session_id.into(),
1466 #[cfg(feature = "unstable_session_system_prompt")]
1467 system_prompt: None,
1468 meta: None,
1469 }
1470 }
1471
1472 #[must_use]
1474 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1475 self.additional_directories = additional_directories;
1476 self
1477 }
1478
1479 #[must_use]
1481 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1482 self.mcp_servers = mcp_servers;
1483 self
1484 }
1485
1486 #[cfg(feature = "unstable_session_system_prompt")]
1492 #[must_use]
1493 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1494 self.system_prompt = system_prompt.into_option();
1495 self
1496 }
1497
1498 #[must_use]
1504 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1505 self.meta = meta.into_option();
1506 self
1507 }
1508}
1509
1510crate::serde_util::default_on_null! {
1511 #[serde_as]
1513 #[skip_serializing_none]
1514 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1515 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1516 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1517 #[serde(rename_all = "camelCase")]
1518 #[non_exhaustive]
1519 pub struct LoadSessionResponse {
1520 #[serde_as(deserialize_as = "DefaultOnError")]
1524 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1525 #[serde(default)]
1526 pub modes: Option<SessionModeState>,
1527 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1529 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1530 #[serde(default)]
1531 pub config_options: Option<Vec<SessionConfigOption>>,
1532 #[serde_as(deserialize_as = "DefaultOnError")]
1538 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1539 #[serde(default)]
1540 #[serde(rename = "_meta")]
1541 pub meta: Option<Meta>,
1542 }
1543}
1544
1545impl LoadSessionResponse {
1546 #[must_use]
1548 pub fn new() -> Self {
1549 Self::default()
1550 }
1551
1552 #[must_use]
1556 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1557 self.modes = modes.into_option();
1558 self
1559 }
1560
1561 #[must_use]
1563 pub fn config_options(
1564 mut self,
1565 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1566 ) -> Self {
1567 self.config_options = config_options.into_option();
1568 self
1569 }
1570
1571 #[must_use]
1577 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1578 self.meta = meta.into_option();
1579 self
1580 }
1581}
1582
1583#[cfg(feature = "unstable_session_fork")]
1596#[serde_as]
1597#[skip_serializing_none]
1598#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1599#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1600#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1601#[serde(rename_all = "camelCase")]
1602#[non_exhaustive]
1603pub struct ForkSessionRequest {
1604 pub session_id: SessionId,
1606 pub cwd: PathBuf,
1608 #[serde_as(deserialize_as = "DefaultOnNull")]
1614 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1615 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1616 pub additional_directories: Vec<PathBuf>,
1617 #[serde_as(deserialize_as = "DefaultOnNull")]
1619 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1620 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1621 pub mcp_servers: Vec<McpServer>,
1622 #[cfg(feature = "unstable_session_system_prompt")]
1634 #[serde(default)]
1635 pub system_prompt: Option<SystemPrompt>,
1636 #[serde_as(deserialize_as = "DefaultOnError")]
1642 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1643 #[serde(default)]
1644 #[serde(rename = "_meta")]
1645 pub meta: Option<Meta>,
1646}
1647
1648#[cfg(feature = "unstable_session_fork")]
1649impl ForkSessionRequest {
1650 #[must_use]
1652 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1653 Self {
1654 session_id: session_id.into(),
1655 cwd: cwd.into(),
1656 additional_directories: vec![],
1657 mcp_servers: vec![],
1658 #[cfg(feature = "unstable_session_system_prompt")]
1659 system_prompt: None,
1660 meta: None,
1661 }
1662 }
1663
1664 #[must_use]
1666 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1667 self.additional_directories = additional_directories;
1668 self
1669 }
1670
1671 #[must_use]
1673 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1674 self.mcp_servers = mcp_servers;
1675 self
1676 }
1677
1678 #[cfg(feature = "unstable_session_system_prompt")]
1684 #[must_use]
1685 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1686 self.system_prompt = system_prompt.into_option();
1687 self
1688 }
1689
1690 #[must_use]
1696 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1697 self.meta = meta.into_option();
1698 self
1699 }
1700}
1701
1702#[cfg(feature = "unstable_session_fork")]
1708#[serde_as]
1709#[skip_serializing_none]
1710#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1711#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1712#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1713#[serde(rename_all = "camelCase")]
1714#[non_exhaustive]
1715pub struct ForkSessionResponse {
1716 pub session_id: SessionId,
1718 #[serde_as(deserialize_as = "DefaultOnError")]
1722 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1723 #[serde(default)]
1724 pub modes: Option<SessionModeState>,
1725 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1727 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1728 #[serde(default)]
1729 pub config_options: Option<Vec<SessionConfigOption>>,
1730 #[serde_as(deserialize_as = "DefaultOnError")]
1736 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1737 #[serde(default)]
1738 #[serde(rename = "_meta")]
1739 pub meta: Option<Meta>,
1740}
1741
1742#[cfg(feature = "unstable_session_fork")]
1743impl ForkSessionResponse {
1744 #[must_use]
1746 pub fn new(session_id: impl Into<SessionId>) -> Self {
1747 Self {
1748 session_id: session_id.into(),
1749 modes: None,
1750 config_options: None,
1751 meta: None,
1752 }
1753 }
1754
1755 #[must_use]
1759 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1760 self.modes = modes.into_option();
1761 self
1762 }
1763
1764 #[must_use]
1766 pub fn config_options(
1767 mut self,
1768 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1769 ) -> Self {
1770 self.config_options = config_options.into_option();
1771 self
1772 }
1773
1774 #[must_use]
1780 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1781 self.meta = meta.into_option();
1782 self
1783 }
1784}
1785
1786#[serde_as]
1795#[skip_serializing_none]
1796#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1797#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1798#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1799#[serde(rename_all = "camelCase")]
1800#[non_exhaustive]
1801pub struct ResumeSessionRequest {
1802 pub session_id: SessionId,
1804 pub cwd: PathBuf,
1806 #[serde_as(deserialize_as = "DefaultOnNull")]
1813 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1814 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1815 pub additional_directories: Vec<PathBuf>,
1816 #[serde_as(deserialize_as = "DefaultOnNull")]
1818 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
1819 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1820 pub mcp_servers: Vec<McpServer>,
1821 #[cfg(feature = "unstable_session_system_prompt")]
1833 #[serde(default)]
1834 pub system_prompt: Option<SystemPrompt>,
1835 #[serde_as(deserialize_as = "DefaultOnError")]
1841 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1842 #[serde(default)]
1843 #[serde(rename = "_meta")]
1844 pub meta: Option<Meta>,
1845}
1846
1847impl ResumeSessionRequest {
1848 #[must_use]
1850 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1851 Self {
1852 session_id: session_id.into(),
1853 cwd: cwd.into(),
1854 additional_directories: vec![],
1855 mcp_servers: vec![],
1856 #[cfg(feature = "unstable_session_system_prompt")]
1857 system_prompt: None,
1858 meta: None,
1859 }
1860 }
1861
1862 #[must_use]
1864 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1865 self.additional_directories = additional_directories;
1866 self
1867 }
1868
1869 #[must_use]
1871 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1872 self.mcp_servers = mcp_servers;
1873 self
1874 }
1875
1876 #[cfg(feature = "unstable_session_system_prompt")]
1882 #[must_use]
1883 pub fn system_prompt(mut self, system_prompt: impl IntoOption<SystemPrompt>) -> Self {
1884 self.system_prompt = system_prompt.into_option();
1885 self
1886 }
1887
1888 #[must_use]
1894 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1895 self.meta = meta.into_option();
1896 self
1897 }
1898}
1899
1900crate::serde_util::default_on_null! {
1901 #[serde_as]
1903 #[skip_serializing_none]
1904 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1905 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1906 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1907 #[serde(rename_all = "camelCase")]
1908 #[non_exhaustive]
1909 pub struct ResumeSessionResponse {
1910 #[serde_as(deserialize_as = "DefaultOnError")]
1914 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1915 #[serde(default)]
1916 pub modes: Option<SessionModeState>,
1917 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_>>>")]
1919 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1920 #[serde(default)]
1921 pub config_options: Option<Vec<SessionConfigOption>>,
1922 #[serde_as(deserialize_as = "DefaultOnError")]
1928 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1929 #[serde(default)]
1930 #[serde(rename = "_meta")]
1931 pub meta: Option<Meta>,
1932 }
1933}
1934
1935impl ResumeSessionResponse {
1936 #[must_use]
1938 pub fn new() -> Self {
1939 Self::default()
1940 }
1941
1942 #[must_use]
1946 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1947 self.modes = modes.into_option();
1948 self
1949 }
1950
1951 #[must_use]
1953 pub fn config_options(
1954 mut self,
1955 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1956 ) -> Self {
1957 self.config_options = config_options.into_option();
1958 self
1959 }
1960
1961 #[must_use]
1967 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1968 self.meta = meta.into_option();
1969 self
1970 }
1971}
1972
1973#[serde_as]
1983#[skip_serializing_none]
1984#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1985#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1986#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1987#[serde(rename_all = "camelCase")]
1988#[non_exhaustive]
1989pub struct CloseSessionRequest {
1990 pub session_id: SessionId,
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
2004impl CloseSessionRequest {
2005 #[must_use]
2007 pub fn new(session_id: impl Into<SessionId>) -> Self {
2008 Self {
2009 session_id: session_id.into(),
2010 meta: None,
2011 }
2012 }
2013
2014 #[must_use]
2020 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2021 self.meta = meta.into_option();
2022 self
2023 }
2024}
2025
2026crate::serde_util::default_on_null! {
2027 #[serde_as]
2029 #[skip_serializing_none]
2030 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2031 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2032 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
2033 #[serde(rename_all = "camelCase")]
2034 #[non_exhaustive]
2035 pub struct CloseSessionResponse {
2036 #[serde_as(deserialize_as = "DefaultOnError")]
2042 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2043 #[serde(default)]
2044 #[serde(rename = "_meta")]
2045 pub meta: Option<Meta>,
2046 }
2047}
2048
2049impl CloseSessionResponse {
2050 #[must_use]
2052 pub fn new() -> Self {
2053 Self::default()
2054 }
2055
2056 #[must_use]
2062 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2063 self.meta = meta.into_option();
2064 self
2065 }
2066}
2067
2068#[cfg(feature = "unstable_session_status")]
2082#[serde_as]
2083#[skip_serializing_none]
2084#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2085#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2086#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_STATUS_METHOD_NAME)))]
2087#[serde(rename_all = "camelCase")]
2088#[non_exhaustive]
2089pub struct SessionStatusRequest {
2090 pub session_id: SessionId,
2092 #[serde_as(deserialize_as = "DefaultOnError")]
2098 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2099 #[serde(default)]
2100 #[serde(rename = "_meta")]
2101 pub meta: Option<Meta>,
2102}
2103
2104#[cfg(feature = "unstable_session_status")]
2105impl SessionStatusRequest {
2106 #[must_use]
2108 pub fn new(session_id: impl Into<SessionId>) -> Self {
2109 Self {
2110 session_id: session_id.into(),
2111 meta: None,
2112 }
2113 }
2114
2115 #[must_use]
2121 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2122 self.meta = meta.into_option();
2123 self
2124 }
2125}
2126
2127#[cfg(feature = "unstable_session_status")]
2136#[serde_as]
2137#[skip_serializing_none]
2138#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2139#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2140#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_STATUS_METHOD_NAME)))]
2141#[serde(rename_all = "camelCase")]
2142#[non_exhaustive]
2143pub struct SessionStatusResponse {
2144 pub status: SessionStatus,
2148 #[serde_as(deserialize_as = "DefaultOnError")]
2154 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2155 #[serde(default)]
2156 #[serde(rename = "_meta")]
2157 pub meta: Option<Meta>,
2158}
2159
2160#[cfg(feature = "unstable_session_status")]
2161impl SessionStatusResponse {
2162 #[must_use]
2164 pub fn new(status: SessionStatus) -> Self {
2165 Self { status, meta: None }
2166 }
2167
2168 #[must_use]
2174 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2175 self.meta = meta.into_option();
2176 self
2177 }
2178}
2179
2180#[cfg(feature = "unstable_session_status")]
2186#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2187#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
2188#[serde(rename_all = "snake_case")]
2189#[non_exhaustive]
2190pub enum SessionStatus {
2191 Open,
2198 Saved,
2202 #[serde(untagged)]
2209 Other(String),
2210}
2211
2212crate::serde_util::default_on_null! {
2215 #[serde_as]
2219 #[skip_serializing_none]
2220 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2221 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2222 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
2223 #[serde(rename_all = "camelCase")]
2224 #[non_exhaustive]
2225 pub struct ListSessionsRequest {
2226 #[serde(default)]
2228 pub cwd: Option<PathBuf>,
2229 #[serde(default)]
2231 pub cursor: Option<String>,
2232 #[cfg(feature = "unstable_session_archive")]
2242 #[serde(default)]
2243 pub archived: Option<SessionArchiveFilter>,
2244 #[serde_as(deserialize_as = "DefaultOnError")]
2250 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2251 #[serde(default)]
2252 #[serde(rename = "_meta")]
2253 pub meta: Option<Meta>,
2254 }
2255}
2256
2257impl ListSessionsRequest {
2258 #[must_use]
2260 pub fn new() -> Self {
2261 Self::default()
2262 }
2263
2264 #[must_use]
2266 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
2267 self.cwd = cwd.into_option();
2268 self
2269 }
2270
2271 #[must_use]
2273 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
2274 self.cursor = cursor.into_option();
2275 self
2276 }
2277
2278 #[cfg(feature = "unstable_session_archive")]
2284 #[must_use]
2285 pub fn archived(mut self, archived: impl IntoOption<SessionArchiveFilter>) -> Self {
2286 self.archived = archived.into_option();
2287 self
2288 }
2289
2290 #[must_use]
2296 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2297 self.meta = meta.into_option();
2298 self
2299 }
2300}
2301
2302#[serde_as]
2304#[skip_serializing_none]
2305#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2306#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2307#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
2308#[serde(rename_all = "camelCase")]
2309#[non_exhaustive]
2310pub struct ListSessionsResponse {
2311 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2313 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2314 pub sessions: Vec<SessionInfo>,
2315 #[serde_as(deserialize_as = "DefaultOnError")]
2318 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2319 #[serde(default)]
2320 pub next_cursor: Option<String>,
2321 #[serde_as(deserialize_as = "DefaultOnError")]
2327 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2328 #[serde(default)]
2329 #[serde(rename = "_meta")]
2330 pub meta: Option<Meta>,
2331}
2332
2333impl ListSessionsResponse {
2334 #[must_use]
2336 pub fn new(sessions: Vec<SessionInfo>) -> Self {
2337 Self {
2338 sessions,
2339 next_cursor: None,
2340 meta: None,
2341 }
2342 }
2343
2344 #[must_use]
2346 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
2347 self.next_cursor = next_cursor.into_option();
2348 self
2349 }
2350
2351 #[must_use]
2357 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2358 self.meta = meta.into_option();
2359 self
2360 }
2361}
2362
2363#[serde_as]
2369#[skip_serializing_none]
2370#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2371#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2372#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
2373#[serde(rename_all = "camelCase")]
2374#[non_exhaustive]
2375pub struct DeleteSessionRequest {
2376 pub session_id: SessionId,
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
2390impl DeleteSessionRequest {
2391 #[must_use]
2393 pub fn new(session_id: impl Into<SessionId>) -> Self {
2394 Self {
2395 session_id: session_id.into(),
2396 meta: None,
2397 }
2398 }
2399
2400 #[must_use]
2406 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2407 self.meta = meta.into_option();
2408 self
2409 }
2410}
2411
2412crate::serde_util::default_on_null! {
2413 #[serde_as]
2415 #[skip_serializing_none]
2416 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2417 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2418 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
2419 #[serde(rename_all = "camelCase")]
2420 #[non_exhaustive]
2421 pub struct DeleteSessionResponse {
2422 #[serde_as(deserialize_as = "DefaultOnError")]
2428 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2429 #[serde(default)]
2430 #[serde(rename = "_meta")]
2431 pub meta: Option<Meta>,
2432 }
2433}
2434
2435impl DeleteSessionResponse {
2436 #[must_use]
2438 pub fn new() -> Self {
2439 Self::default()
2440 }
2441
2442 #[must_use]
2448 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2449 self.meta = meta.into_option();
2450 self
2451 }
2452}
2453
2454#[cfg(feature = "unstable_session_archive")]
2470#[serde_as]
2471#[skip_serializing_none]
2472#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2473#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2474#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_ARCHIVE_METHOD_NAME)))]
2475#[serde(rename_all = "camelCase")]
2476#[non_exhaustive]
2477pub struct ArchiveSessionRequest {
2478 pub session_id: SessionId,
2480 #[serde_as(deserialize_as = "DefaultOnError")]
2486 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2487 #[serde(default)]
2488 #[serde(rename = "_meta")]
2489 pub meta: Option<Meta>,
2490}
2491
2492#[cfg(feature = "unstable_session_archive")]
2493impl ArchiveSessionRequest {
2494 #[must_use]
2496 pub fn new(session_id: impl Into<SessionId>) -> Self {
2497 Self {
2498 session_id: session_id.into(),
2499 meta: None,
2500 }
2501 }
2502
2503 #[must_use]
2509 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2510 self.meta = meta.into_option();
2511 self
2512 }
2513}
2514
2515#[cfg(feature = "unstable_session_archive")]
2516crate::serde_util::default_on_null! {
2517 #[serde_as]
2523 #[skip_serializing_none]
2524 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2525 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2526 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_ARCHIVE_METHOD_NAME)))]
2527 #[serde(rename_all = "camelCase")]
2528 #[non_exhaustive]
2529 pub struct ArchiveSessionResponse {
2530 #[serde_as(deserialize_as = "DefaultOnError")]
2536 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2537 #[serde(default)]
2538 #[serde(rename = "_meta")]
2539 pub meta: Option<Meta>,
2540 }
2541}
2542
2543#[cfg(feature = "unstable_session_archive")]
2544impl ArchiveSessionResponse {
2545 #[must_use]
2547 pub fn new() -> Self {
2548 Self::default()
2549 }
2550
2551 #[must_use]
2557 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2558 self.meta = meta.into_option();
2559 self
2560 }
2561}
2562
2563#[cfg(feature = "unstable_session_archive")]
2578#[serde_as]
2579#[skip_serializing_none]
2580#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2581#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2582#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_UNARCHIVE_METHOD_NAME)))]
2583#[serde(rename_all = "camelCase")]
2584#[non_exhaustive]
2585pub struct UnarchiveSessionRequest {
2586 pub session_id: SessionId,
2588 #[serde_as(deserialize_as = "DefaultOnError")]
2594 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2595 #[serde(default)]
2596 #[serde(rename = "_meta")]
2597 pub meta: Option<Meta>,
2598}
2599
2600#[cfg(feature = "unstable_session_archive")]
2601impl UnarchiveSessionRequest {
2602 #[must_use]
2604 pub fn new(session_id: impl Into<SessionId>) -> Self {
2605 Self {
2606 session_id: session_id.into(),
2607 meta: None,
2608 }
2609 }
2610
2611 #[must_use]
2617 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2618 self.meta = meta.into_option();
2619 self
2620 }
2621}
2622
2623#[cfg(feature = "unstable_session_archive")]
2624crate::serde_util::default_on_null! {
2625 #[serde_as]
2631 #[skip_serializing_none]
2632 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2633 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2634 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_UNARCHIVE_METHOD_NAME)))]
2635 #[serde(rename_all = "camelCase")]
2636 #[non_exhaustive]
2637 pub struct UnarchiveSessionResponse {
2638 #[serde_as(deserialize_as = "DefaultOnError")]
2644 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2645 #[serde(default)]
2646 #[serde(rename = "_meta")]
2647 pub meta: Option<Meta>,
2648 }
2649}
2650
2651#[cfg(feature = "unstable_session_archive")]
2652impl UnarchiveSessionResponse {
2653 #[must_use]
2655 pub fn new() -> Self {
2656 Self::default()
2657 }
2658
2659 #[must_use]
2665 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2666 self.meta = meta.into_option();
2667 self
2668 }
2669}
2670
2671#[cfg(feature = "unstable_session_archive")]
2680#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2681#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
2682#[serde(rename_all = "snake_case")]
2683#[non_exhaustive]
2684pub enum SessionArchiveFilter {
2685 #[default]
2687 Exclude,
2688 Include,
2690 Only,
2692 #[serde(untagged)]
2698 Other(String),
2699}
2700
2701#[serde_as]
2703#[skip_serializing_none]
2704#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2705#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2706#[serde(rename_all = "camelCase")]
2707#[non_exhaustive]
2708pub struct SessionInfo {
2709 pub session_id: SessionId,
2711 pub cwd: PathBuf,
2713 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2719 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2720 #[serde(default, skip_serializing_if = "Vec::is_empty")]
2721 pub additional_directories: Vec<PathBuf>,
2722
2723 #[serde_as(deserialize_as = "DefaultOnError")]
2725 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2726 #[serde(default)]
2727 pub title: Option<String>,
2728 #[serde_as(deserialize_as = "DefaultOnError")]
2730 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2731 #[serde(default)]
2732 pub updated_at: Option<String>,
2733 #[cfg(feature = "unstable_session_archive")]
2742 #[serde_as(deserialize_as = "DefaultOnError")]
2743 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2744 #[serde(default)]
2745 pub archived: Option<bool>,
2746 #[serde_as(deserialize_as = "DefaultOnError")]
2752 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2753 #[serde(default)]
2754 #[serde(rename = "_meta")]
2755 pub meta: Option<Meta>,
2756}
2757
2758impl SessionInfo {
2759 #[must_use]
2761 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
2762 Self {
2763 session_id: session_id.into(),
2764 cwd: cwd.into(),
2765 additional_directories: vec![],
2766 title: None,
2767 updated_at: None,
2768 #[cfg(feature = "unstable_session_archive")]
2769 archived: None,
2770 meta: None,
2771 }
2772 }
2773
2774 #[must_use]
2776 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
2777 self.additional_directories = additional_directories;
2778 self
2779 }
2780
2781 #[must_use]
2783 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
2784 self.title = title.into_option();
2785 self
2786 }
2787
2788 #[must_use]
2790 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
2791 self.updated_at = updated_at.into_option();
2792 self
2793 }
2794
2795 #[cfg(feature = "unstable_session_archive")]
2801 #[must_use]
2802 pub fn archived(mut self, archived: impl IntoOption<bool>) -> Self {
2803 self.archived = archived.into_option();
2804 self
2805 }
2806
2807 #[must_use]
2813 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2814 self.meta = meta.into_option();
2815 self
2816 }
2817}
2818
2819#[cfg(feature = "unstable_session_set_title")]
2835#[serde_as]
2836#[skip_serializing_none]
2837#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2838#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2839#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_TITLE_METHOD_NAME)))]
2840#[serde(rename_all = "camelCase")]
2841#[non_exhaustive]
2842pub struct SetSessionTitleRequest {
2843 pub session_id: SessionId,
2845 pub title: String,
2852 #[serde_as(deserialize_as = "DefaultOnError")]
2858 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2859 #[serde(default)]
2860 #[serde(rename = "_meta")]
2861 pub meta: Option<Meta>,
2862}
2863
2864#[cfg(feature = "unstable_session_set_title")]
2865impl SetSessionTitleRequest {
2866 #[must_use]
2868 pub fn new(session_id: impl Into<SessionId>, title: impl Into<String>) -> Self {
2869 Self {
2870 session_id: session_id.into(),
2871 title: title.into(),
2872 meta: None,
2873 }
2874 }
2875
2876 #[must_use]
2882 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2883 self.meta = meta.into_option();
2884 self
2885 }
2886}
2887
2888#[cfg(feature = "unstable_session_set_title")]
2894#[serde_as]
2895#[skip_serializing_none]
2896#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2897#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2898#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_TITLE_METHOD_NAME)))]
2899#[serde(rename_all = "camelCase")]
2900#[non_exhaustive]
2901pub struct SetSessionTitleResponse {
2902 pub title: String,
2907 #[serde_as(deserialize_as = "DefaultOnError")]
2913 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2914 #[serde(default)]
2915 #[serde(rename = "_meta")]
2916 pub meta: Option<Meta>,
2917}
2918
2919#[cfg(feature = "unstable_session_set_title")]
2920impl SetSessionTitleResponse {
2921 #[must_use]
2923 pub fn new(title: impl Into<String>) -> Self {
2924 Self {
2925 title: title.into(),
2926 meta: None,
2927 }
2928 }
2929
2930 #[must_use]
2936 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2937 self.meta = meta.into_option();
2938 self
2939 }
2940}
2941
2942#[serde_as]
2946#[skip_serializing_none]
2947#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2948#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2949#[serde(rename_all = "camelCase")]
2950#[non_exhaustive]
2951pub struct SessionModeState {
2952 pub current_mode_id: SessionModeId,
2954 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
2956 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2957 pub available_modes: Vec<SessionMode>,
2958 #[serde_as(deserialize_as = "DefaultOnError")]
2964 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2965 #[serde(default)]
2966 #[serde(rename = "_meta")]
2967 pub meta: Option<Meta>,
2968}
2969
2970impl SessionModeState {
2971 #[must_use]
2973 pub fn new(
2974 current_mode_id: impl Into<SessionModeId>,
2975 available_modes: Vec<SessionMode>,
2976 ) -> Self {
2977 Self {
2978 current_mode_id: current_mode_id.into(),
2979 available_modes,
2980 meta: None,
2981 }
2982 }
2983
2984 #[must_use]
2990 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2991 self.meta = meta.into_option();
2992 self
2993 }
2994}
2995
2996#[serde_as]
3000#[skip_serializing_none]
3001#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3002#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3003#[serde(rename_all = "camelCase")]
3004#[non_exhaustive]
3005pub struct SessionMode {
3006 pub id: SessionModeId,
3008 pub name: String,
3010 #[serde_as(deserialize_as = "DefaultOnError")]
3012 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3013 #[serde(default)]
3014 pub description: Option<String>,
3015 #[serde_as(deserialize_as = "DefaultOnError")]
3021 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3022 #[serde(default)]
3023 #[serde(rename = "_meta")]
3024 pub meta: Option<Meta>,
3025}
3026
3027impl SessionMode {
3028 #[must_use]
3030 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
3031 Self {
3032 id: id.into(),
3033 name: name.into(),
3034 description: None,
3035 meta: None,
3036 }
3037 }
3038
3039 #[must_use]
3041 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3042 self.description = description.into_option();
3043 self
3044 }
3045
3046 #[must_use]
3052 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3053 self.meta = meta.into_option();
3054 self
3055 }
3056}
3057
3058#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3060#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3061#[serde(transparent)]
3062#[from(Arc<str>, String, &'static str)]
3063#[non_exhaustive]
3064pub struct SessionModeId(pub Arc<str>);
3065
3066impl SessionModeId {
3067 #[must_use]
3069 pub fn new(id: impl Into<Arc<str>>) -> Self {
3070 Self(id.into())
3071 }
3072}
3073
3074#[serde_as]
3076#[skip_serializing_none]
3077#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3078#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3079#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
3080#[serde(rename_all = "camelCase")]
3081#[non_exhaustive]
3082pub struct SetSessionModeRequest {
3083 pub session_id: SessionId,
3085 pub mode_id: SessionModeId,
3087 #[serde_as(deserialize_as = "DefaultOnError")]
3093 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3094 #[serde(default)]
3095 #[serde(rename = "_meta")]
3096 pub meta: Option<Meta>,
3097}
3098
3099impl SetSessionModeRequest {
3100 #[must_use]
3102 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
3103 Self {
3104 session_id: session_id.into(),
3105 mode_id: mode_id.into(),
3106 meta: None,
3107 }
3108 }
3109
3110 #[must_use]
3112 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3113 self.meta = meta.into_option();
3114 self
3115 }
3116}
3117
3118crate::serde_util::default_on_null! {
3119 #[serde_as]
3121 #[skip_serializing_none]
3122 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3123 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3124 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
3125 #[serde(rename_all = "camelCase")]
3126 #[non_exhaustive]
3127 pub struct SetSessionModeResponse {
3128 #[serde_as(deserialize_as = "DefaultOnError")]
3134 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3135 #[serde(default)]
3136 #[serde(rename = "_meta")]
3137 pub meta: Option<Meta>,
3138 }
3139}
3140
3141impl SetSessionModeResponse {
3142 #[must_use]
3144 pub fn new() -> Self {
3145 Self::default()
3146 }
3147
3148 #[must_use]
3154 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3155 self.meta = meta.into_option();
3156 self
3157 }
3158}
3159
3160#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3164#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3165#[serde(transparent)]
3166#[from(Arc<str>, String, &'static str)]
3167#[non_exhaustive]
3168pub struct SessionConfigId(pub Arc<str>);
3169
3170impl SessionConfigId {
3171 #[must_use]
3173 pub fn new(id: impl Into<Arc<str>>) -> Self {
3174 Self(id.into())
3175 }
3176}
3177
3178#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3180#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3181#[serde(transparent)]
3182#[from(Arc<str>, String, &'static str)]
3183#[non_exhaustive]
3184pub struct SessionConfigValueId(pub Arc<str>);
3185
3186impl SessionConfigValueId {
3187 #[must_use]
3189 pub fn new(id: impl Into<Arc<str>>) -> Self {
3190 Self(id.into())
3191 }
3192}
3193
3194#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3196#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
3197#[serde(transparent)]
3198#[from(Arc<str>, String, &'static str)]
3199#[non_exhaustive]
3200pub struct SessionConfigGroupId(pub Arc<str>);
3201
3202impl SessionConfigGroupId {
3203 #[must_use]
3205 pub fn new(id: impl Into<Arc<str>>) -> Self {
3206 Self(id.into())
3207 }
3208}
3209
3210#[serde_as]
3212#[skip_serializing_none]
3213#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3214#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3215#[serde(rename_all = "camelCase")]
3216#[non_exhaustive]
3217pub struct SessionConfigSelectOption {
3218 pub value: SessionConfigValueId,
3220 pub name: String,
3222 #[serde_as(deserialize_as = "DefaultOnError")]
3224 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3225 #[serde(default)]
3226 pub description: Option<String>,
3227 #[serde_as(deserialize_as = "DefaultOnError")]
3233 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3234 #[serde(default)]
3235 #[serde(rename = "_meta")]
3236 pub meta: Option<Meta>,
3237}
3238
3239impl SessionConfigSelectOption {
3240 #[must_use]
3242 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
3243 Self {
3244 value: value.into(),
3245 name: name.into(),
3246 description: None,
3247 meta: None,
3248 }
3249 }
3250
3251 #[must_use]
3253 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3254 self.description = description.into_option();
3255 self
3256 }
3257
3258 #[must_use]
3264 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3265 self.meta = meta.into_option();
3266 self
3267 }
3268}
3269
3270#[serde_as]
3272#[skip_serializing_none]
3273#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3274#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3275#[serde(rename_all = "camelCase")]
3276#[non_exhaustive]
3277pub struct SessionConfigSelectGroup {
3278 pub group: SessionConfigGroupId,
3280 pub name: String,
3282 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3284 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3285 pub options: Vec<SessionConfigSelectOption>,
3286 #[serde_as(deserialize_as = "DefaultOnError")]
3292 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3293 #[serde(default)]
3294 #[serde(rename = "_meta")]
3295 pub meta: Option<Meta>,
3296}
3297
3298impl SessionConfigSelectGroup {
3299 #[must_use]
3301 pub fn new(
3302 group: impl Into<SessionConfigGroupId>,
3303 name: impl Into<String>,
3304 options: Vec<SessionConfigSelectOption>,
3305 ) -> Self {
3306 Self {
3307 group: group.into(),
3308 name: name.into(),
3309 options,
3310 meta: None,
3311 }
3312 }
3313
3314 #[must_use]
3320 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3321 self.meta = meta.into_option();
3322 self
3323 }
3324}
3325
3326#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3328#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3329#[serde(untagged)]
3330#[non_exhaustive]
3331pub enum SessionConfigSelectOptions {
3332 Ungrouped(Vec<SessionConfigSelectOption>),
3334 Grouped(Vec<SessionConfigSelectGroup>),
3336}
3337
3338impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
3339 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
3340 SessionConfigSelectOptions::Ungrouped(options)
3341 }
3342}
3343
3344impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
3345 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
3346 SessionConfigSelectOptions::Grouped(groups)
3347 }
3348}
3349
3350#[skip_serializing_none]
3352#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3353#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3354#[serde(rename_all = "camelCase")]
3355#[non_exhaustive]
3356pub struct SessionConfigSelect {
3357 pub current_value: SessionConfigValueId,
3359 pub options: SessionConfigSelectOptions,
3361}
3362
3363impl SessionConfigSelect {
3364 #[must_use]
3366 pub fn new(
3367 current_value: impl Into<SessionConfigValueId>,
3368 options: impl Into<SessionConfigSelectOptions>,
3369 ) -> Self {
3370 Self {
3371 current_value: current_value.into(),
3372 options: options.into(),
3373 }
3374 }
3375}
3376
3377#[skip_serializing_none]
3379#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3380#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3381#[serde(rename_all = "camelCase")]
3382#[non_exhaustive]
3383pub struct SessionConfigBoolean {
3384 pub current_value: bool,
3386}
3387
3388impl SessionConfigBoolean {
3389 #[must_use]
3391 pub fn new(current_value: bool) -> Self {
3392 Self { current_value }
3393 }
3394}
3395
3396#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3406#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3407#[serde(rename_all = "snake_case")]
3408#[non_exhaustive]
3409pub enum SessionConfigOptionCategory {
3410 Mode,
3412 Model,
3414 ModelConfig,
3416 ThoughtLevel,
3418 #[serde(untagged)]
3420 Other(String),
3421}
3422
3423#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3425#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3426#[serde(tag = "type", rename_all = "snake_case")]
3427#[cfg_attr(feature = "schemars", schemars(extend("discriminator" = {"propertyName": "type"})))]
3428#[non_exhaustive]
3429pub enum SessionConfigKind {
3430 Select(SessionConfigSelect),
3432 Boolean(SessionConfigBoolean),
3434}
3435
3436#[serde_as]
3438#[skip_serializing_none]
3439#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3440#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3441#[serde(rename_all = "camelCase")]
3442#[non_exhaustive]
3443pub struct SessionConfigOption {
3444 pub id: SessionConfigId,
3446 pub name: String,
3448 #[serde_as(deserialize_as = "DefaultOnError")]
3450 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3451 #[serde(default)]
3452 pub description: Option<String>,
3453 #[serde_as(deserialize_as = "DefaultOnError")]
3455 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3456 #[serde(default)]
3457 pub category: Option<SessionConfigOptionCategory>,
3458 #[serde(flatten)]
3460 pub kind: SessionConfigKind,
3461 #[serde_as(deserialize_as = "DefaultOnError")]
3467 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3468 #[serde(default)]
3469 #[serde(rename = "_meta")]
3470 pub meta: Option<Meta>,
3471}
3472
3473impl SessionConfigOption {
3474 #[must_use]
3476 pub fn new(
3477 id: impl Into<SessionConfigId>,
3478 name: impl Into<String>,
3479 kind: SessionConfigKind,
3480 ) -> Self {
3481 Self {
3482 id: id.into(),
3483 name: name.into(),
3484 description: None,
3485 category: None,
3486 kind,
3487 meta: None,
3488 }
3489 }
3490
3491 #[must_use]
3493 pub fn select(
3494 id: impl Into<SessionConfigId>,
3495 name: impl Into<String>,
3496 current_value: impl Into<SessionConfigValueId>,
3497 options: impl Into<SessionConfigSelectOptions>,
3498 ) -> Self {
3499 Self::new(
3500 id,
3501 name,
3502 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
3503 )
3504 }
3505
3506 #[must_use]
3508 pub fn boolean(
3509 id: impl Into<SessionConfigId>,
3510 name: impl Into<String>,
3511 current_value: bool,
3512 ) -> Self {
3513 Self::new(
3514 id,
3515 name,
3516 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
3517 )
3518 }
3519
3520 #[must_use]
3522 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
3523 self.description = description.into_option();
3524 self
3525 }
3526
3527 #[must_use]
3529 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
3530 self.category = category.into_option();
3531 self
3532 }
3533
3534 #[must_use]
3540 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3541 self.meta = meta.into_option();
3542 self
3543 }
3544}
3545
3546#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3557#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3558#[serde(tag = "type", rename_all = "snake_case")]
3559#[non_exhaustive]
3560pub enum SessionConfigOptionValue {
3561 Boolean {
3563 value: bool,
3565 },
3566 #[serde(untagged)]
3572 ValueId {
3573 value: SessionConfigValueId,
3575 },
3576}
3577
3578impl SessionConfigOptionValue {
3579 #[must_use]
3581 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
3582 Self::ValueId { value: id.into() }
3583 }
3584
3585 #[must_use]
3587 pub fn boolean(val: bool) -> Self {
3588 Self::Boolean { value: val }
3589 }
3590
3591 #[must_use]
3594 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
3595 match self {
3596 Self::ValueId { value } => Some(value),
3597 _ => None,
3598 }
3599 }
3600
3601 #[must_use]
3603 pub fn as_bool(&self) -> Option<bool> {
3604 match self {
3605 Self::Boolean { value } => Some(*value),
3606 _ => None,
3607 }
3608 }
3609}
3610
3611impl From<SessionConfigValueId> for SessionConfigOptionValue {
3612 fn from(value: SessionConfigValueId) -> Self {
3613 Self::ValueId { value }
3614 }
3615}
3616
3617impl From<bool> for SessionConfigOptionValue {
3618 fn from(value: bool) -> Self {
3619 Self::Boolean { value }
3620 }
3621}
3622
3623impl From<&str> for SessionConfigOptionValue {
3624 fn from(value: &str) -> Self {
3625 Self::ValueId {
3626 value: SessionConfigValueId::new(value),
3627 }
3628 }
3629}
3630
3631#[serde_as]
3633#[skip_serializing_none]
3634#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3635#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3636#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
3637#[serde(rename_all = "camelCase")]
3638#[non_exhaustive]
3639pub struct SetSessionConfigOptionRequest {
3640 pub session_id: SessionId,
3642 pub config_id: SessionConfigId,
3644 #[serde(flatten)]
3649 pub value: SessionConfigOptionValue,
3650 #[serde_as(deserialize_as = "DefaultOnError")]
3656 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3657 #[serde(default)]
3658 #[serde(rename = "_meta")]
3659 pub meta: Option<Meta>,
3660}
3661
3662impl SetSessionConfigOptionRequest {
3663 #[must_use]
3665 pub fn new(
3666 session_id: impl Into<SessionId>,
3667 config_id: impl Into<SessionConfigId>,
3668 value: impl Into<SessionConfigOptionValue>,
3669 ) -> Self {
3670 Self {
3671 session_id: session_id.into(),
3672 config_id: config_id.into(),
3673 value: value.into(),
3674 meta: None,
3675 }
3676 }
3677
3678 #[must_use]
3684 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3685 self.meta = meta.into_option();
3686 self
3687 }
3688}
3689
3690#[serde_as]
3692#[skip_serializing_none]
3693#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3694#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3695#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
3696#[serde(rename_all = "camelCase")]
3697#[non_exhaustive]
3698pub struct SetSessionConfigOptionResponse {
3699 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
3701 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3702 pub config_options: Vec<SessionConfigOption>,
3703 #[serde_as(deserialize_as = "DefaultOnError")]
3709 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3710 #[serde(default)]
3711 #[serde(rename = "_meta")]
3712 pub meta: Option<Meta>,
3713}
3714
3715impl SetSessionConfigOptionResponse {
3716 #[must_use]
3718 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
3719 Self {
3720 config_options,
3721 meta: None,
3722 }
3723 }
3724
3725 #[must_use]
3731 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3732 self.meta = meta.into_option();
3733 self
3734 }
3735}
3736
3737#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3746#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3747#[serde(tag = "type", rename_all = "snake_case")]
3748#[non_exhaustive]
3749pub enum McpServer {
3750 Http(McpServerHttp),
3754 Sse(McpServerSse),
3758 #[cfg(feature = "unstable_mcp_over_acp")]
3767 Acp(McpServerAcp),
3768 #[serde(untagged)]
3772 Stdio(McpServerStdio),
3773}
3774
3775#[serde_as]
3777#[skip_serializing_none]
3778#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3779#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3780#[serde(rename_all = "camelCase")]
3781#[non_exhaustive]
3782pub struct McpServerHttp {
3783 pub name: String,
3785 pub url: String,
3787 #[serde_as(deserialize_as = "DefaultOnNull")]
3789 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3790 pub headers: Vec<HttpHeader>,
3791 #[serde_as(deserialize_as = "DefaultOnError")]
3797 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3798 #[serde(default)]
3799 #[serde(rename = "_meta")]
3800 pub meta: Option<Meta>,
3801}
3802
3803impl McpServerHttp {
3804 #[must_use]
3806 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
3807 Self {
3808 name: name.into(),
3809 url: url.into(),
3810 headers: Vec::new(),
3811 meta: None,
3812 }
3813 }
3814
3815 #[must_use]
3817 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
3818 self.headers = headers;
3819 self
3820 }
3821
3822 #[must_use]
3828 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3829 self.meta = meta.into_option();
3830 self
3831 }
3832}
3833
3834#[serde_as]
3836#[skip_serializing_none]
3837#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3838#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3839#[serde(rename_all = "camelCase")]
3840#[non_exhaustive]
3841pub struct McpServerSse {
3842 pub name: String,
3844 pub url: String,
3846 #[serde_as(deserialize_as = "DefaultOnNull")]
3848 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3849 pub headers: Vec<HttpHeader>,
3850 #[serde_as(deserialize_as = "DefaultOnError")]
3856 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3857 #[serde(default)]
3858 #[serde(rename = "_meta")]
3859 pub meta: Option<Meta>,
3860}
3861
3862impl McpServerSse {
3863 #[must_use]
3865 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
3866 Self {
3867 name: name.into(),
3868 url: url.into(),
3869 headers: Vec::new(),
3870 meta: None,
3871 }
3872 }
3873
3874 #[must_use]
3876 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
3877 self.headers = headers;
3878 self
3879 }
3880
3881 #[must_use]
3887 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3888 self.meta = meta.into_option();
3889 self
3890 }
3891}
3892
3893#[cfg(feature = "unstable_mcp_over_acp")]
3902#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3903#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
3904#[serde(transparent)]
3905#[from(Arc<str>, String, &'static str)]
3906#[non_exhaustive]
3907pub struct McpServerAcpId(pub Arc<str>);
3908
3909#[cfg(feature = "unstable_mcp_over_acp")]
3910impl McpServerAcpId {
3911 #[must_use]
3913 pub fn new(id: impl Into<Arc<str>>) -> Self {
3914 Self(id.into())
3915 }
3916}
3917
3918#[serde_as]
3927#[skip_serializing_none]
3928#[cfg(feature = "unstable_mcp_over_acp")]
3929#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3930#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3931#[serde(rename_all = "camelCase")]
3932#[non_exhaustive]
3933pub struct McpServerAcp {
3934 pub name: String,
3936 pub server_id: McpServerAcpId,
3941 #[serde_as(deserialize_as = "DefaultOnError")]
3947 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3948 #[serde(default)]
3949 #[serde(rename = "_meta")]
3950 pub meta: Option<Meta>,
3951}
3952
3953#[cfg(feature = "unstable_mcp_over_acp")]
3954impl McpServerAcp {
3955 #[must_use]
3957 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
3958 Self {
3959 name: name.into(),
3960 server_id: id.into(),
3961 meta: None,
3962 }
3963 }
3964
3965 #[must_use]
3971 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3972 self.meta = meta.into_option();
3973 self
3974 }
3975}
3976
3977#[serde_as]
3979#[skip_serializing_none]
3980#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3981#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3982#[serde(rename_all = "camelCase")]
3983#[non_exhaustive]
3984pub struct McpServerStdio {
3985 pub name: String,
3987 pub command: PathBuf,
3989 #[serde_as(deserialize_as = "DefaultOnNull")]
3991 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3992 pub args: Vec<String>,
3993 #[serde_as(deserialize_as = "DefaultOnNull")]
3995 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-null" = true)))]
3996 pub env: Vec<EnvVariable>,
3997 #[serde_as(deserialize_as = "DefaultOnError")]
4003 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4004 #[serde(default)]
4005 #[serde(rename = "_meta")]
4006 pub meta: Option<Meta>,
4007}
4008
4009impl McpServerStdio {
4010 #[must_use]
4012 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
4013 Self {
4014 name: name.into(),
4015 command: command.into(),
4016 args: Vec::new(),
4017 env: Vec::new(),
4018 meta: None,
4019 }
4020 }
4021
4022 #[must_use]
4024 pub fn args(mut self, args: Vec<String>) -> Self {
4025 self.args = args;
4026 self
4027 }
4028
4029 #[must_use]
4031 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
4032 self.env = env;
4033 self
4034 }
4035
4036 #[must_use]
4042 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4043 self.meta = meta.into_option();
4044 self
4045 }
4046}
4047
4048#[serde_as]
4050#[skip_serializing_none]
4051#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4052#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4053#[serde(rename_all = "camelCase")]
4054#[non_exhaustive]
4055pub struct EnvVariable {
4056 pub name: String,
4058 pub value: String,
4060 #[serde_as(deserialize_as = "DefaultOnError")]
4066 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4067 #[serde(default)]
4068 #[serde(rename = "_meta")]
4069 pub meta: Option<Meta>,
4070}
4071
4072impl EnvVariable {
4073 #[must_use]
4075 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
4076 Self {
4077 name: name.into(),
4078 value: value.into(),
4079 meta: None,
4080 }
4081 }
4082
4083 #[must_use]
4089 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4090 self.meta = meta.into_option();
4091 self
4092 }
4093}
4094
4095#[serde_as]
4097#[skip_serializing_none]
4098#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4099#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4100#[serde(rename_all = "camelCase")]
4101#[non_exhaustive]
4102pub struct HttpHeader {
4103 pub name: String,
4105 pub value: String,
4107 #[serde_as(deserialize_as = "DefaultOnError")]
4113 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4114 #[serde(default)]
4115 #[serde(rename = "_meta")]
4116 pub meta: Option<Meta>,
4117}
4118
4119impl HttpHeader {
4120 #[must_use]
4122 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
4123 Self {
4124 name: name.into(),
4125 value: value.into(),
4126 meta: None,
4127 }
4128 }
4129
4130 #[must_use]
4136 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4137 self.meta = meta.into_option();
4138 self
4139 }
4140}
4141
4142#[cfg(feature = "unstable_session_system_prompt")]
4156#[serde_as]
4157#[skip_serializing_none]
4158#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4159#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4160#[serde(rename_all = "camelCase")]
4161#[non_exhaustive]
4162pub struct SystemPrompt {
4163 pub mode: SystemPromptMode,
4168 pub content: Vec<ContentBlock>,
4178 #[serde_as(deserialize_as = "DefaultOnError")]
4184 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4185 #[serde(default)]
4186 #[serde(rename = "_meta")]
4187 pub meta: Option<Meta>,
4188}
4189
4190#[cfg(feature = "unstable_session_system_prompt")]
4191impl SystemPrompt {
4192 #[must_use]
4197 pub fn new(content: Vec<ContentBlock>) -> Self {
4198 Self {
4199 mode: SystemPromptMode::default(),
4200 content,
4201 meta: None,
4202 }
4203 }
4204
4205 #[must_use]
4207 pub fn mode(mut self, mode: SystemPromptMode) -> Self {
4208 self.mode = mode;
4209 self
4210 }
4211
4212 #[must_use]
4218 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4219 self.meta = meta.into_option();
4220 self
4221 }
4222}
4223
4224#[cfg(feature = "unstable_session_system_prompt")]
4234#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4235#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
4236#[serde(rename_all = "snake_case")]
4237#[non_exhaustive]
4238pub enum SystemPromptMode {
4239 #[default]
4246 Append,
4247 Override,
4256 #[serde(untagged)]
4262 Other(String),
4263}
4264
4265#[serde_as]
4273#[skip_serializing_none]
4274#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4275#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4276#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
4277#[serde(rename_all = "camelCase")]
4278#[non_exhaustive]
4279pub struct PromptRequest {
4280 pub session_id: SessionId,
4282 pub prompt: Vec<ContentBlock>,
4296 #[serde_as(deserialize_as = "DefaultOnError")]
4302 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4303 #[serde(default)]
4304 #[serde(rename = "_meta")]
4305 pub meta: Option<Meta>,
4306}
4307
4308impl PromptRequest {
4309 #[must_use]
4311 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
4312 Self {
4313 session_id: session_id.into(),
4314 prompt,
4315 meta: None,
4316 }
4317 }
4318
4319 #[must_use]
4325 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4326 self.meta = meta.into_option();
4327 self
4328 }
4329}
4330
4331#[serde_as]
4335#[skip_serializing_none]
4336#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4337#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4338#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
4339#[serde(rename_all = "camelCase")]
4340#[non_exhaustive]
4341pub struct PromptResponse {
4342 pub stop_reason: StopReason,
4344 #[cfg(feature = "unstable_end_turn_token_usage")]
4350 #[serde_as(deserialize_as = "DefaultOnError")]
4351 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4352 #[serde(default)]
4353 pub usage: Option<Usage>,
4354 #[serde_as(deserialize_as = "DefaultOnError")]
4360 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4361 #[serde(default)]
4362 #[serde(rename = "_meta")]
4363 pub meta: Option<Meta>,
4364}
4365
4366impl PromptResponse {
4367 #[must_use]
4369 pub fn new(stop_reason: StopReason) -> Self {
4370 Self {
4371 stop_reason,
4372 #[cfg(feature = "unstable_end_turn_token_usage")]
4373 usage: None,
4374 meta: None,
4375 }
4376 }
4377
4378 #[cfg(feature = "unstable_end_turn_token_usage")]
4384 #[must_use]
4385 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
4386 self.usage = usage.into_option();
4387 self
4388 }
4389
4390 #[must_use]
4396 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4397 self.meta = meta.into_option();
4398 self
4399 }
4400}
4401
4402#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4406#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
4407#[serde(rename_all = "snake_case")]
4408#[non_exhaustive]
4409pub enum StopReason {
4410 EndTurn,
4412 MaxTokens,
4414 MaxTurnRequests,
4417 Refusal,
4421 Cancelled,
4428}
4429
4430#[cfg(feature = "unstable_end_turn_token_usage")]
4436#[serde_as]
4437#[skip_serializing_none]
4438#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4439#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4440#[serde(rename_all = "camelCase")]
4441#[non_exhaustive]
4442pub struct Usage {
4443 pub total_tokens: u64,
4445 pub input_tokens: u64,
4447 pub output_tokens: u64,
4449 #[serde_as(deserialize_as = "DefaultOnError")]
4451 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4452 #[serde(default)]
4453 pub thought_tokens: Option<u64>,
4454 #[serde_as(deserialize_as = "DefaultOnError")]
4456 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4457 #[serde(default)]
4458 pub cached_read_tokens: Option<u64>,
4459 #[serde_as(deserialize_as = "DefaultOnError")]
4461 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4462 #[serde(default)]
4463 pub cached_write_tokens: Option<u64>,
4464 #[serde_as(deserialize_as = "DefaultOnError")]
4470 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4471 #[serde(default)]
4472 #[serde(rename = "_meta")]
4473 pub meta: Option<Meta>,
4474}
4475
4476#[cfg(feature = "unstable_end_turn_token_usage")]
4477impl Usage {
4478 #[must_use]
4480 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
4481 Self {
4482 total_tokens,
4483 input_tokens,
4484 output_tokens,
4485 thought_tokens: None,
4486 cached_read_tokens: None,
4487 cached_write_tokens: None,
4488 meta: None,
4489 }
4490 }
4491
4492 #[must_use]
4494 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
4495 self.thought_tokens = thought_tokens.into_option();
4496 self
4497 }
4498
4499 #[must_use]
4501 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
4502 self.cached_read_tokens = cached_read_tokens.into_option();
4503 self
4504 }
4505
4506 #[must_use]
4508 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
4509 self.cached_write_tokens = cached_write_tokens.into_option();
4510 self
4511 }
4512
4513 #[must_use]
4519 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4520 self.meta = meta.into_option();
4521 self
4522 }
4523}
4524
4525#[cfg(feature = "unstable_llm_providers")]
4538#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4539#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4540#[serde(rename_all = "snake_case")]
4541#[non_exhaustive]
4542#[expect(clippy::doc_markdown)]
4543pub enum LlmProtocol {
4544 Anthropic,
4546 #[serde(rename = "openai")]
4548 OpenAi,
4549 Azure,
4551 Vertex,
4553 Bedrock,
4555 #[serde(untagged)]
4557 Other(String),
4558}
4559
4560#[cfg(feature = "unstable_llm_providers")]
4566#[serde_as]
4567#[skip_serializing_none]
4568#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4569#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4570#[serde(rename_all = "camelCase")]
4571#[non_exhaustive]
4572pub struct ProviderCurrentConfig {
4573 pub api_type: LlmProtocol,
4575 pub base_url: String,
4577 #[serde_as(deserialize_as = "DefaultOnError")]
4583 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4584 #[serde(default)]
4585 #[serde(rename = "_meta")]
4586 pub meta: Option<Meta>,
4587}
4588
4589#[cfg(feature = "unstable_llm_providers")]
4590impl ProviderCurrentConfig {
4591 #[must_use]
4593 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
4594 Self {
4595 api_type,
4596 base_url: base_url.into(),
4597 meta: None,
4598 }
4599 }
4600
4601 #[must_use]
4607 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4608 self.meta = meta.into_option();
4609 self
4610 }
4611}
4612
4613#[cfg(feature = "unstable_llm_providers")]
4619#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4620#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
4621#[serde(transparent)]
4622#[from(Arc<str>, String, &'static str)]
4623#[non_exhaustive]
4624pub struct ProviderId(pub Arc<str>);
4625
4626#[cfg(feature = "unstable_llm_providers")]
4627impl ProviderId {
4628 #[must_use]
4630 pub fn new(id: impl Into<Arc<str>>) -> Self {
4631 Self(id.into())
4632 }
4633}
4634
4635#[cfg(feature = "unstable_llm_providers")]
4641#[serde_as]
4642#[skip_serializing_none]
4643#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4644#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4645#[serde(rename_all = "camelCase")]
4646#[non_exhaustive]
4647pub struct ProviderInfo {
4648 pub provider_id: ProviderId,
4650 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_>>")]
4652 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
4653 pub supported: Vec<LlmProtocol>,
4654 pub required: bool,
4657 #[serde(default)]
4660 pub current: Option<ProviderCurrentConfig>,
4661 #[serde_as(deserialize_as = "DefaultOnError")]
4667 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4668 #[serde(default)]
4669 #[serde(rename = "_meta")]
4670 pub meta: Option<Meta>,
4671}
4672
4673#[cfg(feature = "unstable_llm_providers")]
4674impl ProviderInfo {
4675 #[must_use]
4677 pub fn new(
4678 provider_id: impl Into<ProviderId>,
4679 supported: Vec<LlmProtocol>,
4680 required: bool,
4681 current: impl IntoOption<ProviderCurrentConfig>,
4682 ) -> Self {
4683 Self {
4684 provider_id: provider_id.into(),
4685 supported,
4686 required,
4687 current: current.into_option(),
4688 meta: None,
4689 }
4690 }
4691
4692 #[must_use]
4698 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4699 self.meta = meta.into_option();
4700 self
4701 }
4702}
4703
4704#[cfg(feature = "unstable_llm_providers")]
4705crate::serde_util::default_on_null! {
4706 #[serde_as]
4712 #[skip_serializing_none]
4713 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4714 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4715 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
4716 #[serde(rename_all = "camelCase")]
4717 #[non_exhaustive]
4718 pub struct ListProvidersRequest {
4719 #[serde_as(deserialize_as = "DefaultOnError")]
4725 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4726 #[serde(default)]
4727 #[serde(rename = "_meta")]
4728 pub meta: Option<Meta>,
4729 }
4730}
4731
4732#[cfg(feature = "unstable_llm_providers")]
4733impl ListProvidersRequest {
4734 #[must_use]
4736 pub fn new() -> Self {
4737 Self::default()
4738 }
4739
4740 #[must_use]
4746 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4747 self.meta = meta.into_option();
4748 self
4749 }
4750}
4751
4752#[cfg(feature = "unstable_llm_providers")]
4758#[serde_as]
4759#[skip_serializing_none]
4760#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4761#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4762#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
4763#[serde(rename_all = "camelCase")]
4764#[non_exhaustive]
4765pub struct ListProvidersResponse {
4766 pub providers: Vec<ProviderInfo>,
4768 #[serde_as(deserialize_as = "DefaultOnError")]
4774 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4775 #[serde(default)]
4776 #[serde(rename = "_meta")]
4777 pub meta: Option<Meta>,
4778}
4779
4780#[cfg(feature = "unstable_llm_providers")]
4781impl ListProvidersResponse {
4782 #[must_use]
4784 pub fn new(providers: Vec<ProviderInfo>) -> Self {
4785 Self {
4786 providers,
4787 meta: None,
4788 }
4789 }
4790
4791 #[must_use]
4797 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4798 self.meta = meta.into_option();
4799 self
4800 }
4801}
4802
4803#[cfg(feature = "unstable_llm_providers")]
4811#[serde_as]
4812#[skip_serializing_none]
4813#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4814#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
4815#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
4816#[serde(rename_all = "camelCase")]
4817#[non_exhaustive]
4818pub struct SetProviderRequest {
4819 pub provider_id: ProviderId,
4821 pub api_type: LlmProtocol,
4823 pub base_url: String,
4825 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
4828 pub headers: HashMap<String, String>,
4829 #[serde_as(deserialize_as = "DefaultOnError")]
4835 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4836 #[serde(default)]
4837 #[serde(rename = "_meta")]
4838 pub meta: Option<Meta>,
4839}
4840
4841#[cfg(feature = "unstable_llm_providers")]
4842impl SetProviderRequest {
4843 #[must_use]
4845 pub fn new(
4846 provider_id: impl Into<ProviderId>,
4847 api_type: LlmProtocol,
4848 base_url: impl Into<String>,
4849 ) -> Self {
4850 Self {
4851 provider_id: provider_id.into(),
4852 api_type,
4853 base_url: base_url.into(),
4854 headers: HashMap::new(),
4855 meta: None,
4856 }
4857 }
4858
4859 #[must_use]
4862 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
4863 self.headers = headers;
4864 self
4865 }
4866
4867 #[must_use]
4873 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4874 self.meta = meta.into_option();
4875 self
4876 }
4877}
4878
4879#[cfg(feature = "unstable_llm_providers")]
4880crate::serde_util::default_on_null! {
4881 #[serde_as]
4887 #[skip_serializing_none]
4888 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4889 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4890 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
4891 #[serde(rename_all = "camelCase")]
4892 #[non_exhaustive]
4893 pub struct SetProviderResponse {
4894 #[serde_as(deserialize_as = "DefaultOnError")]
4900 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4901 #[serde(default)]
4902 #[serde(rename = "_meta")]
4903 pub meta: Option<Meta>,
4904 }
4905}
4906
4907#[cfg(feature = "unstable_llm_providers")]
4908impl SetProviderResponse {
4909 #[must_use]
4911 pub fn new() -> Self {
4912 Self::default()
4913 }
4914
4915 #[must_use]
4921 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4922 self.meta = meta.into_option();
4923 self
4924 }
4925}
4926
4927#[cfg(feature = "unstable_llm_providers")]
4933#[serde_as]
4934#[skip_serializing_none]
4935#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4936#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4937#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
4938#[serde(rename_all = "camelCase")]
4939#[non_exhaustive]
4940pub struct DisableProviderRequest {
4941 pub provider_id: ProviderId,
4943 #[serde_as(deserialize_as = "DefaultOnError")]
4949 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4950 #[serde(default)]
4951 #[serde(rename = "_meta")]
4952 pub meta: Option<Meta>,
4953}
4954
4955#[cfg(feature = "unstable_llm_providers")]
4956impl DisableProviderRequest {
4957 #[must_use]
4959 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
4960 Self {
4961 provider_id: provider_id.into(),
4962 meta: None,
4963 }
4964 }
4965
4966 #[must_use]
4972 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4973 self.meta = meta.into_option();
4974 self
4975 }
4976}
4977
4978#[cfg(feature = "unstable_llm_providers")]
4979crate::serde_util::default_on_null! {
4980 #[serde_as]
4986 #[skip_serializing_none]
4987 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4988 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
4989 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
4990 #[serde(rename_all = "camelCase")]
4991 #[non_exhaustive]
4992 pub struct DisableProviderResponse {
4993 #[serde_as(deserialize_as = "DefaultOnError")]
4999 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5000 #[serde(default)]
5001 #[serde(rename = "_meta")]
5002 pub meta: Option<Meta>,
5003 }
5004}
5005
5006#[cfg(feature = "unstable_llm_providers")]
5007impl DisableProviderResponse {
5008 #[must_use]
5010 pub fn new() -> Self {
5011 Self::default()
5012 }
5013
5014 #[must_use]
5020 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5021 self.meta = meta.into_option();
5022 self
5023 }
5024}
5025
5026#[serde_as]
5035#[skip_serializing_none]
5036#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5037#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5038#[serde(rename_all = "camelCase")]
5039#[non_exhaustive]
5040pub struct AgentCapabilities {
5041 #[serde_as(deserialize_as = "DefaultOnError")]
5043 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5044 #[serde(default)]
5045 pub load_session: bool,
5046 #[serde_as(deserialize_as = "DefaultOnError")]
5048 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5049 #[serde(default)]
5050 pub prompt_capabilities: PromptCapabilities,
5051 #[serde_as(deserialize_as = "DefaultOnError")]
5053 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5054 #[serde(default)]
5055 pub mcp_capabilities: McpCapabilities,
5056 #[serde_as(deserialize_as = "DefaultOnError")]
5058 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5059 #[serde(default)]
5060 pub session_capabilities: SessionCapabilities,
5061 #[serde_as(deserialize_as = "DefaultOnError")]
5063 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5064 #[serde(default)]
5065 pub auth: AgentAuthCapabilities,
5066 #[cfg(feature = "unstable_llm_providers")]
5075 #[serde_as(deserialize_as = "DefaultOnError")]
5076 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5077 #[serde(default)]
5078 pub providers: Option<ProvidersCapabilities>,
5079 #[serde_as(deserialize_as = "DefaultOnError")]
5085 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5086 #[serde(default)]
5087 #[serde(rename = "_meta")]
5088 pub meta: Option<Meta>,
5089}
5090
5091impl AgentCapabilities {
5092 #[must_use]
5094 pub fn new() -> Self {
5095 Self::default()
5096 }
5097
5098 #[must_use]
5100 pub fn load_session(mut self, load_session: bool) -> Self {
5101 self.load_session = load_session;
5102 self
5103 }
5104
5105 #[must_use]
5107 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
5108 self.prompt_capabilities = prompt_capabilities;
5109 self
5110 }
5111
5112 #[must_use]
5114 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
5115 self.mcp_capabilities = mcp_capabilities;
5116 self
5117 }
5118
5119 #[must_use]
5121 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
5122 self.session_capabilities = session_capabilities;
5123 self
5124 }
5125
5126 #[must_use]
5128 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
5129 self.auth = auth;
5130 self
5131 }
5132
5133 #[cfg(feature = "unstable_llm_providers")]
5139 #[must_use]
5140 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
5141 self.providers = providers.into_option();
5142 self
5143 }
5144
5145 #[must_use]
5151 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5152 self.meta = meta.into_option();
5153 self
5154 }
5155}
5156
5157#[cfg(feature = "unstable_llm_providers")]
5165#[serde_as]
5166#[skip_serializing_none]
5167#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5168#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5169#[non_exhaustive]
5170pub struct ProvidersCapabilities {
5171 #[serde_as(deserialize_as = "DefaultOnError")]
5177 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5178 #[serde(default)]
5179 #[serde(rename = "_meta")]
5180 pub meta: Option<Meta>,
5181}
5182
5183#[cfg(feature = "unstable_llm_providers")]
5184impl ProvidersCapabilities {
5185 #[must_use]
5187 pub fn new() -> Self {
5188 Self::default()
5189 }
5190
5191 #[must_use]
5197 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5198 self.meta = meta.into_option();
5199 self
5200 }
5201}
5202
5203#[serde_as]
5213#[skip_serializing_none]
5214#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5215#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5216#[serde(rename_all = "camelCase")]
5217#[non_exhaustive]
5218pub struct SessionCapabilities {
5219 #[serde_as(deserialize_as = "DefaultOnError")]
5224 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5225 #[serde(default)]
5226 pub list: Option<SessionListCapabilities>,
5227 #[serde_as(deserialize_as = "DefaultOnError")]
5232 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5233 #[serde(default)]
5234 pub delete: Option<SessionDeleteCapabilities>,
5235 #[serde_as(deserialize_as = "DefaultOnError")]
5245 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5246 #[serde(default)]
5247 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
5248 #[cfg(feature = "unstable_session_system_prompt")]
5257 #[serde_as(deserialize_as = "DefaultOnError")]
5258 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5259 #[serde(default)]
5260 pub system_prompt: Option<SessionSystemPromptCapabilities>,
5261 #[cfg(feature = "unstable_session_fork")]
5270 #[serde_as(deserialize_as = "DefaultOnError")]
5271 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5272 #[serde(default)]
5273 pub fork: Option<SessionForkCapabilities>,
5274 #[cfg(feature = "unstable_session_archive")]
5284 #[serde_as(deserialize_as = "DefaultOnError")]
5285 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5286 #[serde(default)]
5287 pub archive: Option<SessionArchiveCapabilities>,
5288 #[cfg(feature = "unstable_session_status")]
5297 #[serde_as(deserialize_as = "DefaultOnError")]
5298 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5299 #[serde(default)]
5300 pub status: Option<SessionStatusCapabilities>,
5301 #[cfg(feature = "unstable_session_set_title")]
5313 #[serde_as(deserialize_as = "DefaultOnError")]
5314 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5315 #[serde(default)]
5316 pub title: Option<SessionTitleCapabilities>,
5317 #[serde_as(deserialize_as = "DefaultOnError")]
5322 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5323 #[serde(default)]
5324 pub resume: Option<SessionResumeCapabilities>,
5325 #[serde_as(deserialize_as = "DefaultOnError")]
5330 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5331 #[serde(default)]
5332 pub close: Option<SessionCloseCapabilities>,
5333 #[serde_as(deserialize_as = "DefaultOnError")]
5339 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5340 #[serde(default)]
5341 #[serde(rename = "_meta")]
5342 pub meta: Option<Meta>,
5343}
5344
5345impl SessionCapabilities {
5346 #[must_use]
5348 pub fn new() -> Self {
5349 Self::default()
5350 }
5351
5352 #[must_use]
5357 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
5358 self.list = list.into_option();
5359 self
5360 }
5361
5362 #[must_use]
5367 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
5368 self.delete = delete.into_option();
5369 self
5370 }
5371
5372 #[must_use]
5382 pub fn additional_directories(
5383 mut self,
5384 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
5385 ) -> Self {
5386 self.additional_directories = additional_directories.into_option();
5387 self
5388 }
5389
5390 #[cfg(feature = "unstable_session_system_prompt")]
5399 #[must_use]
5400 pub fn system_prompt(
5401 mut self,
5402 system_prompt: impl IntoOption<SessionSystemPromptCapabilities>,
5403 ) -> Self {
5404 self.system_prompt = system_prompt.into_option();
5405 self
5406 }
5407
5408 #[cfg(feature = "unstable_session_fork")]
5409 #[must_use]
5414 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
5415 self.fork = fork.into_option();
5416 self
5417 }
5418
5419 #[cfg(feature = "unstable_session_archive")]
5429 #[must_use]
5430 pub fn archive(mut self, archive: impl IntoOption<SessionArchiveCapabilities>) -> Self {
5431 self.archive = archive.into_option();
5432 self
5433 }
5434
5435 #[cfg(feature = "unstable_session_status")]
5444 #[must_use]
5445 pub fn status(mut self, status: impl IntoOption<SessionStatusCapabilities>) -> Self {
5446 self.status = status.into_option();
5447 self
5448 }
5449
5450 #[cfg(feature = "unstable_session_set_title")]
5462 #[must_use]
5463 pub fn title(mut self, title: impl IntoOption<SessionTitleCapabilities>) -> Self {
5464 self.title = title.into_option();
5465 self
5466 }
5467
5468 #[must_use]
5473 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
5474 self.resume = resume.into_option();
5475 self
5476 }
5477
5478 #[must_use]
5483 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
5484 self.close = close.into_option();
5485 self
5486 }
5487
5488 #[must_use]
5494 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5495 self.meta = meta.into_option();
5496 self
5497 }
5498}
5499
5500#[serde_as]
5504#[skip_serializing_none]
5505#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5506#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5507#[non_exhaustive]
5508pub struct SessionListCapabilities {
5509 #[serde_as(deserialize_as = "DefaultOnError")]
5515 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5516 #[serde(default)]
5517 #[serde(rename = "_meta")]
5518 pub meta: Option<Meta>,
5519}
5520
5521impl SessionListCapabilities {
5522 #[must_use]
5524 pub fn new() -> Self {
5525 Self::default()
5526 }
5527
5528 #[must_use]
5534 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5535 self.meta = meta.into_option();
5536 self
5537 }
5538}
5539
5540#[serde_as]
5544#[skip_serializing_none]
5545#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5546#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5547#[non_exhaustive]
5548pub struct SessionDeleteCapabilities {
5549 #[serde_as(deserialize_as = "DefaultOnError")]
5555 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5556 #[serde(default)]
5557 #[serde(rename = "_meta")]
5558 pub meta: Option<Meta>,
5559}
5560
5561impl SessionDeleteCapabilities {
5562 #[must_use]
5564 pub fn new() -> Self {
5565 Self::default()
5566 }
5567
5568 #[must_use]
5574 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5575 self.meta = meta.into_option();
5576 self
5577 }
5578}
5579
5580#[serde_as]
5587#[skip_serializing_none]
5588#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5589#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5590#[non_exhaustive]
5591pub struct SessionAdditionalDirectoriesCapabilities {
5592 #[serde_as(deserialize_as = "DefaultOnError")]
5598 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5599 #[serde(default)]
5600 #[serde(rename = "_meta")]
5601 pub meta: Option<Meta>,
5602}
5603
5604impl SessionAdditionalDirectoriesCapabilities {
5605 #[must_use]
5607 pub fn new() -> Self {
5608 Self::default()
5609 }
5610
5611 #[must_use]
5617 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5618 self.meta = meta.into_option();
5619 self
5620 }
5621}
5622
5623#[cfg(feature = "unstable_session_system_prompt")]
5632#[serde_as]
5633#[skip_serializing_none]
5634#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5635#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5636#[serde(rename_all = "camelCase")]
5637#[non_exhaustive]
5638pub struct SessionSystemPromptCapabilities {
5639 #[serde_as(deserialize_as = "DefaultOnError")]
5643 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5644 #[serde(default)]
5645 pub mode: Option<SessionSystemPromptModeCapabilities>,
5646 #[serde_as(deserialize_as = "DefaultOnError")]
5652 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5653 #[serde(default)]
5654 #[serde(rename = "_meta")]
5655 pub meta: Option<Meta>,
5656}
5657
5658#[cfg(feature = "unstable_session_system_prompt")]
5659impl SessionSystemPromptCapabilities {
5660 #[must_use]
5662 pub fn new() -> Self {
5663 Self::default()
5664 }
5665
5666 #[must_use]
5670 pub fn mode(mut self, mode: impl IntoOption<SessionSystemPromptModeCapabilities>) -> Self {
5671 self.mode = mode.into_option();
5672 self
5673 }
5674
5675 #[must_use]
5681 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5682 self.meta = meta.into_option();
5683 self
5684 }
5685}
5686
5687#[cfg(feature = "unstable_session_system_prompt")]
5696#[serde_as]
5697#[skip_serializing_none]
5698#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5699#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5700#[serde(rename_all = "camelCase")]
5701#[non_exhaustive]
5702pub struct SessionSystemPromptModeCapabilities {
5703 #[serde_as(deserialize_as = "DefaultOnError")]
5709 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5710 #[serde(default, rename = "override")]
5711 pub override_: Option<SessionSystemPromptOverrideCapabilities>,
5712 #[serde_as(deserialize_as = "DefaultOnError")]
5718 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5719 #[serde(default)]
5720 #[serde(rename = "_meta")]
5721 pub meta: Option<Meta>,
5722}
5723
5724#[cfg(feature = "unstable_session_system_prompt")]
5725impl SessionSystemPromptModeCapabilities {
5726 #[must_use]
5728 pub fn new() -> Self {
5729 Self::default()
5730 }
5731
5732 #[must_use]
5738 pub fn override_(
5739 mut self,
5740 override_: impl IntoOption<SessionSystemPromptOverrideCapabilities>,
5741 ) -> Self {
5742 self.override_ = override_.into_option();
5743 self
5744 }
5745
5746 #[must_use]
5752 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5753 self.meta = meta.into_option();
5754 self
5755 }
5756}
5757
5758#[cfg(feature = "unstable_session_system_prompt")]
5767#[serde_as]
5768#[skip_serializing_none]
5769#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5770#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5771#[non_exhaustive]
5772pub struct SessionSystemPromptOverrideCapabilities {
5773 #[serde_as(deserialize_as = "DefaultOnError")]
5779 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5780 #[serde(default)]
5781 #[serde(rename = "_meta")]
5782 pub meta: Option<Meta>,
5783}
5784
5785#[cfg(feature = "unstable_session_system_prompt")]
5786impl SessionSystemPromptOverrideCapabilities {
5787 #[must_use]
5789 pub fn new() -> Self {
5790 Self::default()
5791 }
5792
5793 #[must_use]
5799 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5800 self.meta = meta.into_option();
5801 self
5802 }
5803}
5804
5805#[cfg(feature = "unstable_session_fork")]
5813#[serde_as]
5814#[skip_serializing_none]
5815#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5816#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5817#[non_exhaustive]
5818pub struct SessionForkCapabilities {
5819 #[serde_as(deserialize_as = "DefaultOnError")]
5825 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5826 #[serde(default)]
5827 #[serde(rename = "_meta")]
5828 pub meta: Option<Meta>,
5829}
5830
5831#[cfg(feature = "unstable_session_fork")]
5832impl SessionForkCapabilities {
5833 #[must_use]
5835 pub fn new() -> Self {
5836 Self::default()
5837 }
5838
5839 #[must_use]
5845 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5846 self.meta = meta.into_option();
5847 self
5848 }
5849}
5850
5851#[cfg(feature = "unstable_session_archive")]
5860#[serde_as]
5861#[skip_serializing_none]
5862#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5863#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5864#[non_exhaustive]
5865pub struct SessionArchiveCapabilities {
5866 #[serde_as(deserialize_as = "DefaultOnError")]
5872 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5873 #[serde(default)]
5874 #[serde(rename = "_meta")]
5875 pub meta: Option<Meta>,
5876}
5877
5878#[cfg(feature = "unstable_session_archive")]
5879impl SessionArchiveCapabilities {
5880 #[must_use]
5882 pub fn new() -> Self {
5883 Self::default()
5884 }
5885
5886 #[must_use]
5892 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5893 self.meta = meta.into_option();
5894 self
5895 }
5896}
5897
5898#[cfg(feature = "unstable_session_status")]
5906#[serde_as]
5907#[skip_serializing_none]
5908#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5909#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5910#[non_exhaustive]
5911pub struct SessionStatusCapabilities {
5912 #[serde_as(deserialize_as = "DefaultOnError")]
5918 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5919 #[serde(default)]
5920 #[serde(rename = "_meta")]
5921 pub meta: Option<Meta>,
5922}
5923
5924#[cfg(feature = "unstable_session_status")]
5925impl SessionStatusCapabilities {
5926 #[must_use]
5928 pub fn new() -> Self {
5929 Self::default()
5930 }
5931
5932 #[must_use]
5938 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5939 self.meta = meta.into_option();
5940 self
5941 }
5942}
5943
5944#[cfg(feature = "unstable_session_set_title")]
5953#[serde_as]
5954#[skip_serializing_none]
5955#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5956#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5957#[non_exhaustive]
5958pub struct SessionTitleCapabilities {
5959 #[serde_as(deserialize_as = "DefaultOnError")]
5965 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5966 #[serde(default)]
5967 #[serde(rename = "_meta")]
5968 pub meta: Option<Meta>,
5969}
5970
5971#[cfg(feature = "unstable_session_set_title")]
5972impl SessionTitleCapabilities {
5973 #[must_use]
5975 pub fn new() -> Self {
5976 Self::default()
5977 }
5978
5979 #[must_use]
5985 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5986 self.meta = meta.into_option();
5987 self
5988 }
5989}
5990
5991#[serde_as]
5995#[skip_serializing_none]
5996#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5997#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5998#[non_exhaustive]
5999pub struct SessionResumeCapabilities {
6000 #[serde_as(deserialize_as = "DefaultOnError")]
6006 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6007 #[serde(default)]
6008 #[serde(rename = "_meta")]
6009 pub meta: Option<Meta>,
6010}
6011
6012impl SessionResumeCapabilities {
6013 #[must_use]
6015 pub fn new() -> Self {
6016 Self::default()
6017 }
6018
6019 #[must_use]
6025 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6026 self.meta = meta.into_option();
6027 self
6028 }
6029}
6030
6031#[serde_as]
6035#[skip_serializing_none]
6036#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6037#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6038#[non_exhaustive]
6039pub struct SessionCloseCapabilities {
6040 #[serde_as(deserialize_as = "DefaultOnError")]
6046 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6047 #[serde(default)]
6048 #[serde(rename = "_meta")]
6049 pub meta: Option<Meta>,
6050}
6051
6052impl SessionCloseCapabilities {
6053 #[must_use]
6055 pub fn new() -> Self {
6056 Self::default()
6057 }
6058
6059 #[must_use]
6065 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6066 self.meta = meta.into_option();
6067 self
6068 }
6069}
6070
6071#[serde_as]
6084#[skip_serializing_none]
6085#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6086#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6087#[serde(rename_all = "camelCase")]
6088#[non_exhaustive]
6089pub struct PromptCapabilities {
6090 #[serde_as(deserialize_as = "DefaultOnError")]
6092 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6093 #[serde(default)]
6094 pub image: bool,
6095 #[serde_as(deserialize_as = "DefaultOnError")]
6097 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6098 #[serde(default)]
6099 pub audio: bool,
6100 #[serde_as(deserialize_as = "DefaultOnError")]
6105 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6106 #[serde(default)]
6107 pub embedded_context: bool,
6108 #[serde_as(deserialize_as = "DefaultOnError")]
6114 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6115 #[serde(default)]
6116 #[serde(rename = "_meta")]
6117 pub meta: Option<Meta>,
6118}
6119
6120impl PromptCapabilities {
6121 #[must_use]
6123 pub fn new() -> Self {
6124 Self::default()
6125 }
6126
6127 #[must_use]
6129 pub fn image(mut self, image: bool) -> Self {
6130 self.image = image;
6131 self
6132 }
6133
6134 #[must_use]
6136 pub fn audio(mut self, audio: bool) -> Self {
6137 self.audio = audio;
6138 self
6139 }
6140
6141 #[must_use]
6146 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
6147 self.embedded_context = embedded_context;
6148 self
6149 }
6150
6151 #[must_use]
6157 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6158 self.meta = meta.into_option();
6159 self
6160 }
6161}
6162
6163#[serde_as]
6165#[skip_serializing_none]
6166#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6167#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6168#[serde(rename_all = "camelCase")]
6169#[non_exhaustive]
6170pub struct McpCapabilities {
6171 #[serde_as(deserialize_as = "DefaultOnError")]
6173 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6174 #[serde(default)]
6175 pub http: bool,
6176 #[serde_as(deserialize_as = "DefaultOnError")]
6178 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6179 #[serde(default)]
6180 pub sse: bool,
6181 #[cfg(feature = "unstable_mcp_over_acp")]
6187 #[serde_as(deserialize_as = "DefaultOnError")]
6188 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6189 #[serde(default)]
6190 pub acp: bool,
6191 #[serde_as(deserialize_as = "DefaultOnError")]
6197 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6198 #[serde(default)]
6199 #[serde(rename = "_meta")]
6200 pub meta: Option<Meta>,
6201}
6202
6203impl McpCapabilities {
6204 #[must_use]
6206 pub fn new() -> Self {
6207 Self::default()
6208 }
6209
6210 #[must_use]
6212 pub fn http(mut self, http: bool) -> Self {
6213 self.http = http;
6214 self
6215 }
6216
6217 #[must_use]
6219 pub fn sse(mut self, sse: bool) -> Self {
6220 self.sse = sse;
6221 self
6222 }
6223
6224 #[cfg(feature = "unstable_mcp_over_acp")]
6230 #[must_use]
6231 pub fn acp(mut self, acp: bool) -> Self {
6232 self.acp = acp;
6233 self
6234 }
6235
6236 #[must_use]
6242 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6243 self.meta = meta.into_option();
6244 self
6245 }
6246}
6247
6248#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6254#[non_exhaustive]
6255pub struct AgentMethodNames {
6256 pub initialize: &'static str,
6258 pub authenticate: &'static str,
6260 #[cfg(feature = "unstable_llm_providers")]
6262 pub providers_list: &'static str,
6263 #[cfg(feature = "unstable_llm_providers")]
6265 pub providers_set: &'static str,
6266 #[cfg(feature = "unstable_llm_providers")]
6268 pub providers_disable: &'static str,
6269 pub session_new: &'static str,
6271 pub session_load: &'static str,
6273 pub session_set_mode: &'static str,
6275 pub session_set_config_option: &'static str,
6277 pub session_prompt: &'static str,
6279 pub session_cancel: &'static str,
6281 #[cfg(feature = "unstable_mcp_over_acp")]
6283 pub mcp_message: &'static str,
6284 pub session_list: &'static str,
6286 pub session_delete: &'static str,
6288 #[cfg(feature = "unstable_session_fork")]
6290 pub session_fork: &'static str,
6291 #[cfg(feature = "unstable_session_archive")]
6293 pub session_archive: &'static str,
6294 #[cfg(feature = "unstable_session_archive")]
6296 pub session_unarchive: &'static str,
6297 #[cfg(feature = "unstable_session_status")]
6299 pub session_status: &'static str,
6300 #[cfg(feature = "unstable_session_set_title")]
6302 pub session_set_title: &'static str,
6303 pub session_resume: &'static str,
6305 pub session_close: &'static str,
6307 pub logout: &'static str,
6309 #[cfg(feature = "unstable_auth_status")]
6311 pub auth_status: &'static str,
6312}
6313
6314pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
6316 initialize: INITIALIZE_METHOD_NAME,
6317 authenticate: AUTHENTICATE_METHOD_NAME,
6318 #[cfg(feature = "unstable_llm_providers")]
6319 providers_list: PROVIDERS_LIST_METHOD_NAME,
6320 #[cfg(feature = "unstable_llm_providers")]
6321 providers_set: PROVIDERS_SET_METHOD_NAME,
6322 #[cfg(feature = "unstable_llm_providers")]
6323 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
6324 session_new: SESSION_NEW_METHOD_NAME,
6325 session_load: SESSION_LOAD_METHOD_NAME,
6326 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
6327 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
6328 session_prompt: SESSION_PROMPT_METHOD_NAME,
6329 session_cancel: SESSION_CANCEL_METHOD_NAME,
6330 #[cfg(feature = "unstable_mcp_over_acp")]
6331 mcp_message: MCP_MESSAGE_METHOD_NAME,
6332 session_list: SESSION_LIST_METHOD_NAME,
6333 session_delete: SESSION_DELETE_METHOD_NAME,
6334 #[cfg(feature = "unstable_session_fork")]
6335 session_fork: SESSION_FORK_METHOD_NAME,
6336 #[cfg(feature = "unstable_session_archive")]
6337 session_archive: SESSION_ARCHIVE_METHOD_NAME,
6338 #[cfg(feature = "unstable_session_archive")]
6339 session_unarchive: SESSION_UNARCHIVE_METHOD_NAME,
6340 #[cfg(feature = "unstable_session_status")]
6341 session_status: SESSION_STATUS_METHOD_NAME,
6342 #[cfg(feature = "unstable_session_set_title")]
6343 session_set_title: SESSION_SET_TITLE_METHOD_NAME,
6344 session_resume: SESSION_RESUME_METHOD_NAME,
6345 session_close: SESSION_CLOSE_METHOD_NAME,
6346 logout: LOGOUT_METHOD_NAME,
6347 #[cfg(feature = "unstable_auth_status")]
6348 auth_status: AUTH_STATUS_METHOD_NAME,
6349};
6350
6351pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
6353pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
6355#[cfg(feature = "unstable_llm_providers")]
6357pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
6358#[cfg(feature = "unstable_llm_providers")]
6360pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
6361#[cfg(feature = "unstable_llm_providers")]
6363pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
6364pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
6366pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
6368pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
6370pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
6372pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
6374pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
6376pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
6378pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
6380#[cfg(feature = "unstable_session_fork")]
6382pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
6383#[cfg(feature = "unstable_session_archive")]
6385pub(crate) const SESSION_ARCHIVE_METHOD_NAME: &str = "session/archive";
6386#[cfg(feature = "unstable_session_archive")]
6388pub(crate) const SESSION_UNARCHIVE_METHOD_NAME: &str = "session/unarchive";
6389#[cfg(feature = "unstable_session_status")]
6391pub(crate) const SESSION_STATUS_METHOD_NAME: &str = "session/status";
6392#[cfg(feature = "unstable_session_set_title")]
6394pub(crate) const SESSION_SET_TITLE_METHOD_NAME: &str = "session/set_title";
6395pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
6397pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
6399pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
6401#[cfg(feature = "unstable_auth_status")]
6403pub(crate) const AUTH_STATUS_METHOD_NAME: &str = "auth/status";
6404
6405#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6412#[derive(Clone, Debug, Serialize, Deserialize)]
6413#[serde(untagged)]
6414#[cfg_attr(feature = "schemars", schemars(inline))]
6415#[non_exhaustive]
6416#[allow(clippy::large_enum_variant)]
6417pub enum ClientRequest {
6418 InitializeRequest(InitializeRequest),
6429 AuthenticateRequest(AuthenticateRequest),
6440 #[cfg(feature = "unstable_llm_providers")]
6446 ListProvidersRequest(ListProvidersRequest),
6447 #[cfg(feature = "unstable_llm_providers")]
6453 SetProviderRequest(SetProviderRequest),
6454 #[cfg(feature = "unstable_llm_providers")]
6460 DisableProviderRequest(DisableProviderRequest),
6461 LogoutRequest(LogoutRequest),
6466 #[cfg(feature = "unstable_auth_status")]
6475 AuthStatusRequest(AuthStatusRequest),
6476 NewSessionRequest(NewSessionRequest),
6489 LoadSessionRequest(LoadSessionRequest),
6500 ListSessionsRequest(ListSessionsRequest),
6506 DeleteSessionRequest(DeleteSessionRequest),
6510 #[cfg(feature = "unstable_session_fork")]
6511 ForkSessionRequest(ForkSessionRequest),
6527 #[cfg(feature = "unstable_session_archive")]
6528 ArchiveSessionRequest(ArchiveSessionRequest),
6536 #[cfg(feature = "unstable_session_archive")]
6537 UnarchiveSessionRequest(UnarchiveSessionRequest),
6545 #[cfg(feature = "unstable_session_status")]
6546 SessionStatusRequest(SessionStatusRequest),
6554 #[cfg(feature = "unstable_session_set_title")]
6555 SetSessionTitleRequest(SetSessionTitleRequest),
6566 ResumeSessionRequest(ResumeSessionRequest),
6573 CloseSessionRequest(CloseSessionRequest),
6580 SetSessionModeRequest(SetSessionModeRequest),
6594 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
6596 PromptRequest(PromptRequest),
6608 ExtMethodRequest(ExtRequest),
6615}
6616
6617impl ClientRequest {
6618 #[must_use]
6620 pub fn method(&self) -> &str {
6621 match self {
6622 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
6623 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
6624 #[cfg(feature = "unstable_llm_providers")]
6625 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
6626 #[cfg(feature = "unstable_llm_providers")]
6627 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
6628 #[cfg(feature = "unstable_llm_providers")]
6629 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
6630 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
6631 #[cfg(feature = "unstable_auth_status")]
6632 Self::AuthStatusRequest(_) => AGENT_METHOD_NAMES.auth_status,
6633 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
6634 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
6635 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
6636 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
6637 #[cfg(feature = "unstable_session_fork")]
6638 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
6639 #[cfg(feature = "unstable_session_archive")]
6640 Self::ArchiveSessionRequest(_) => AGENT_METHOD_NAMES.session_archive,
6641 #[cfg(feature = "unstable_session_archive")]
6642 Self::UnarchiveSessionRequest(_) => AGENT_METHOD_NAMES.session_unarchive,
6643 #[cfg(feature = "unstable_session_status")]
6644 Self::SessionStatusRequest(_) => AGENT_METHOD_NAMES.session_status,
6645 #[cfg(feature = "unstable_session_set_title")]
6646 Self::SetSessionTitleRequest(_) => AGENT_METHOD_NAMES.session_set_title,
6647 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
6648 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
6649 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
6650 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
6651 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
6652 Self::ExtMethodRequest(ext_request) => &ext_request.method,
6653 }
6654 }
6655}
6656
6657#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6664#[derive(Clone, Debug, Serialize, Deserialize)]
6665#[serde(untagged)]
6666#[cfg_attr(feature = "schemars", schemars(inline))]
6667#[non_exhaustive]
6668#[allow(clippy::large_enum_variant)]
6669pub enum AgentResponse {
6670 InitializeResponse(InitializeResponse),
6672 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
6674 #[cfg(feature = "unstable_llm_providers")]
6676 ListProvidersResponse(ListProvidersResponse),
6677 #[cfg(feature = "unstable_llm_providers")]
6679 SetProviderResponse(#[serde(default)] SetProviderResponse),
6680 #[cfg(feature = "unstable_llm_providers")]
6682 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
6683 LogoutResponse(#[serde(default)] LogoutResponse),
6685 #[cfg(feature = "unstable_auth_status")]
6687 AuthStatusResponse(AuthStatusResponse),
6688 NewSessionResponse(NewSessionResponse),
6690 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
6692 ListSessionsResponse(ListSessionsResponse),
6694 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
6696 #[cfg(feature = "unstable_session_fork")]
6698 ForkSessionResponse(ForkSessionResponse),
6699 #[cfg(feature = "unstable_session_archive")]
6701 ArchiveSessionResponse(#[serde(default)] ArchiveSessionResponse),
6702 #[cfg(feature = "unstable_session_archive")]
6704 UnarchiveSessionResponse(#[serde(default)] UnarchiveSessionResponse),
6705 #[cfg(feature = "unstable_session_status")]
6707 SessionStatusResponse(SessionStatusResponse),
6708 #[cfg(feature = "unstable_session_set_title")]
6710 SetSessionTitleResponse(SetSessionTitleResponse),
6711 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
6713 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
6715 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
6717 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
6719 PromptResponse(PromptResponse),
6721 ExtMethodResponse(ExtResponse),
6723}
6724
6725#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6732#[derive(Clone, Debug, Serialize, Deserialize)]
6733#[serde(untagged)]
6734#[cfg_attr(feature = "schemars", schemars(inline))]
6735#[non_exhaustive]
6736#[allow(clippy::large_enum_variant)]
6737pub enum ClientNotification {
6738 CancelNotification(CancelNotification),
6750 #[cfg(feature = "unstable_mcp_over_acp")]
6756 MessageMcpNotification(MessageMcpNotification),
6757 ExtNotification(ExtNotification),
6764}
6765
6766impl ClientNotification {
6767 #[must_use]
6769 pub fn method(&self) -> &str {
6770 match self {
6771 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
6772 #[cfg(feature = "unstable_mcp_over_acp")]
6773 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
6774 Self::ExtNotification(ext_notification) => &ext_notification.method,
6775 }
6776 }
6777}
6778
6779#[serde_as]
6783#[skip_serializing_none]
6784#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
6785#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
6786#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME)))]
6787#[serde(rename_all = "camelCase")]
6788#[non_exhaustive]
6789pub struct CancelNotification {
6790 pub session_id: SessionId,
6792 #[serde_as(deserialize_as = "DefaultOnError")]
6798 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
6799 #[serde(default)]
6800 #[serde(rename = "_meta")]
6801 pub meta: Option<Meta>,
6802}
6803
6804impl CancelNotification {
6805 #[must_use]
6807 pub fn new(session_id: impl Into<SessionId>) -> Self {
6808 Self {
6809 session_id: session_id.into(),
6810 meta: None,
6811 }
6812 }
6813
6814 #[must_use]
6820 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
6821 self.meta = meta.into_option();
6822 self
6823 }
6824}
6825
6826#[cfg(test)]
6827mod test_serialization {
6828 use super::*;
6829 use serde_json::json;
6830
6831 fn test_meta() -> Meta {
6832 json!({ "source": "test" }).as_object().unwrap().clone()
6833 }
6834
6835 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
6836 serde_json::to_string(value)
6837 .unwrap()
6838 .matches("\"_meta\"")
6839 .count()
6840 }
6841
6842 #[test]
6845 fn prompt_response_has_no_error_stop_reason() {
6846 assert_eq!(
6847 serde_json::from_value::<PromptResponse>(json!({ "stopReason": "end_turn" }))
6848 .unwrap()
6849 .stop_reason,
6850 StopReason::EndTurn
6851 );
6852 assert!(
6853 serde_json::from_value::<PromptResponse>(json!({ "stopReason": "error" })).is_err()
6854 );
6855 }
6856
6857 #[test]
6858 fn test_initialize_capabilities_default_on_malformed_values() {
6859 let request: InitializeRequest = serde_json::from_value(json!({
6860 "protocolVersion": 1,
6861 "clientCapabilities": false
6862 }))
6863 .unwrap();
6864 assert_eq!(request.client_capabilities, ClientCapabilities::default());
6865
6866 let response: InitializeResponse = serde_json::from_value(json!({
6867 "protocolVersion": 1,
6868 "agentCapabilities": false
6869 }))
6870 .unwrap();
6871 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
6872 }
6873
6874 #[test]
6875 fn test_agent_capabilities_default_on_malformed_values() {
6876 let capabilities: AgentCapabilities = serde_json::from_value(json!({
6877 "loadSession": "yes",
6878 "promptCapabilities": {
6879 "image": "yes",
6880 "audio": true,
6881 "embeddedContext": {}
6882 },
6883 "mcpCapabilities": {
6884 "http": "yes",
6885 "sse": true
6886 },
6887 "sessionCapabilities": false,
6888 "auth": false
6889 }))
6890 .unwrap();
6891
6892 assert!(!capabilities.load_session);
6893 assert!(!capabilities.prompt_capabilities.image);
6894 assert!(capabilities.prompt_capabilities.audio);
6895 assert!(!capabilities.prompt_capabilities.embedded_context);
6896 assert!(!capabilities.mcp_capabilities.http);
6897 assert!(capabilities.mcp_capabilities.sse);
6898 assert_eq!(
6899 capabilities.session_capabilities,
6900 SessionCapabilities::default()
6901 );
6902 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
6903 }
6904
6905 #[test]
6906 fn test_mcp_server_stdio_serialization() {
6907 let server = McpServer::Stdio(
6908 McpServerStdio::new("test-server", "/usr/bin/server")
6909 .args(vec!["--port".to_string(), "3000".to_string()])
6910 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
6911 );
6912
6913 let json = serde_json::to_value(&server).unwrap();
6914 assert_eq!(
6915 json,
6916 json!({
6917 "name": "test-server",
6918 "command": "/usr/bin/server",
6919 "args": ["--port", "3000"],
6920 "env": [
6921 {
6922 "name": "API_KEY",
6923 "value": "secret123"
6924 }
6925 ]
6926 })
6927 );
6928
6929 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6930 match deserialized {
6931 McpServer::Stdio(McpServerStdio {
6932 name,
6933 command,
6934 args,
6935 env,
6936 meta: _,
6937 }) => {
6938 assert_eq!(name, "test-server");
6939 assert_eq!(command, PathBuf::from("/usr/bin/server"));
6940 assert_eq!(args, vec!["--port", "3000"]);
6941 assert_eq!(env.len(), 1);
6942 assert_eq!(env[0].name, "API_KEY");
6943 assert_eq!(env[0].value, "secret123");
6944 }
6945 _ => panic!("Expected Stdio variant"),
6946 }
6947 }
6948
6949 #[test]
6950 fn test_mcp_server_http_serialization() {
6951 let server = McpServer::Http(
6952 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
6953 HttpHeader::new("Authorization", "Bearer token123"),
6954 HttpHeader::new("Content-Type", "application/json"),
6955 ]),
6956 );
6957
6958 let json = serde_json::to_value(&server).unwrap();
6959 assert_eq!(
6960 json,
6961 json!({
6962 "type": "http",
6963 "name": "http-server",
6964 "url": "https://api.example.com",
6965 "headers": [
6966 {
6967 "name": "Authorization",
6968 "value": "Bearer token123"
6969 },
6970 {
6971 "name": "Content-Type",
6972 "value": "application/json"
6973 }
6974 ]
6975 })
6976 );
6977
6978 let deserialized: McpServer = serde_json::from_value(json).unwrap();
6979 match deserialized {
6980 McpServer::Http(McpServerHttp {
6981 name,
6982 url,
6983 headers,
6984 meta: _,
6985 }) => {
6986 assert_eq!(name, "http-server");
6987 assert_eq!(url, "https://api.example.com");
6988 assert_eq!(headers.len(), 2);
6989 assert_eq!(headers[0].name, "Authorization");
6990 assert_eq!(headers[0].value, "Bearer token123");
6991 assert_eq!(headers[1].name, "Content-Type");
6992 assert_eq!(headers[1].value, "application/json");
6993 }
6994 _ => panic!("Expected Http variant"),
6995 }
6996 }
6997
6998 #[cfg(feature = "unstable_mcp_over_acp")]
6999 #[test]
7000 fn test_mcp_server_acp_serialization() {
7001 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
7002
7003 let json = serde_json::to_value(&server).unwrap();
7004 assert_eq!(
7005 json,
7006 json!({
7007 "type": "acp",
7008 "name": "project-tools",
7009 "serverId": "project-tools-id"
7010 })
7011 );
7012
7013 let deserialized: McpServer = serde_json::from_value(json).unwrap();
7014 match deserialized {
7015 McpServer::Acp(McpServerAcp {
7016 name,
7017 server_id: id,
7018 meta: _,
7019 }) => {
7020 assert_eq!(name, "project-tools");
7021 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
7022 }
7023 _ => panic!("Expected Acp variant"),
7024 }
7025 }
7026
7027 #[cfg(feature = "unstable_mcp_over_acp")]
7028 #[test]
7029 fn test_client_mcp_message_method_names() {
7030 use serde_json::json;
7031
7032 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
7033
7034 let notification =
7035 MessageMcpNotification::new("server-1", "req-1", "notifications/progress");
7036 assert_eq!(
7037 ClientNotification::MessageMcpNotification(notification.clone()).method(),
7038 "mcp/message"
7039 );
7040 assert_eq!(
7041 serde_json::to_value(notification).unwrap(),
7042 json!({
7043 "serverId": "server-1",
7044 "requestId": "req-1",
7045 "method": "notifications/progress"
7046 })
7047 );
7048 let notification: MessageMcpNotification = serde_json::from_value(json!({
7049 "serverId": "server-1", "requestId": "req-1", "method": "notifications/progress",
7050 "params": null, "_meta": null
7051 }))
7052 .unwrap();
7053 assert_eq!(notification.params, None);
7054 assert_eq!(notification.meta, None);
7055 for key in ["serverId", "requestId", "method"] {
7056 let mut value = json!({"serverId":"server-1", "requestId":"req-1", "method":"notifications/progress"});
7057 value.as_object_mut().unwrap().remove(key);
7058 assert!(serde_json::from_value::<MessageMcpNotification>(value).is_err());
7059 }
7060 }
7061
7062 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7063 #[test]
7064 fn test_mcp_server_acp_schema() {
7065 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
7066 assert!(json_contains_entry(
7067 &mcp_server_schema,
7068 "const",
7069 &json!("acp")
7070 ));
7071 assert!(json_contains_entry(
7072 &mcp_server_schema,
7073 "$ref",
7074 &json!("#/$defs/McpServerAcp")
7075 ));
7076
7077 let capabilities_schema =
7078 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
7079 assert!(json_contains_key(&capabilities_schema, "acp"));
7080 }
7081
7082 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7083 fn json_contains_entry(
7084 value: &serde_json::Value,
7085 key: &str,
7086 expected: &serde_json::Value,
7087 ) -> bool {
7088 match value {
7089 serde_json::Value::Object(map) => {
7090 map.get(key) == Some(expected)
7091 || map
7092 .values()
7093 .any(|value| json_contains_entry(value, key, expected))
7094 }
7095 serde_json::Value::Array(values) => values
7096 .iter()
7097 .any(|value| json_contains_entry(value, key, expected)),
7098 _ => false,
7099 }
7100 }
7101
7102 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
7103 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
7104 match value {
7105 serde_json::Value::Object(map) => {
7106 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
7107 }
7108 serde_json::Value::Array(values) => {
7109 values.iter().any(|value| json_contains_key(value, key))
7110 }
7111 _ => false,
7112 }
7113 }
7114
7115 #[test]
7116 fn test_mcp_server_sse_serialization() {
7117 let server = McpServer::Sse(
7118 McpServerSse::new("sse-server", "https://sse.example.com/events")
7119 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
7120 );
7121
7122 let json = serde_json::to_value(&server).unwrap();
7123 assert_eq!(
7124 json,
7125 json!({
7126 "type": "sse",
7127 "name": "sse-server",
7128 "url": "https://sse.example.com/events",
7129 "headers": [
7130 {
7131 "name": "X-API-Key",
7132 "value": "apikey456"
7133 }
7134 ]
7135 })
7136 );
7137
7138 let deserialized: McpServer = serde_json::from_value(json).unwrap();
7139 match deserialized {
7140 McpServer::Sse(McpServerSse {
7141 name,
7142 url,
7143 headers,
7144 meta: _,
7145 }) => {
7146 assert_eq!(name, "sse-server");
7147 assert_eq!(url, "https://sse.example.com/events");
7148 assert_eq!(headers.len(), 1);
7149 assert_eq!(headers[0].name, "X-API-Key");
7150 assert_eq!(headers[0].value, "apikey456");
7151 }
7152 _ => panic!("Expected Sse variant"),
7153 }
7154 }
7155
7156 #[test]
7157 fn test_session_config_option_category_known_variants() {
7158 assert_eq!(
7160 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
7161 json!("mode")
7162 );
7163 assert_eq!(
7164 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
7165 json!("model")
7166 );
7167 assert_eq!(
7168 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
7169 json!("model_config")
7170 );
7171 assert_eq!(
7172 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
7173 json!("thought_level")
7174 );
7175
7176 assert_eq!(
7178 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
7179 SessionConfigOptionCategory::Mode
7180 );
7181 assert_eq!(
7182 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
7183 SessionConfigOptionCategory::Model
7184 );
7185 assert_eq!(
7186 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
7187 SessionConfigOptionCategory::ModelConfig
7188 );
7189 assert_eq!(
7190 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
7191 SessionConfigOptionCategory::ThoughtLevel
7192 );
7193 }
7194
7195 #[test]
7196 fn test_session_config_option_category_unknown_variants() {
7197 let unknown: SessionConfigOptionCategory =
7199 serde_json::from_str("\"some_future_category\"").unwrap();
7200 assert_eq!(
7201 unknown,
7202 SessionConfigOptionCategory::Other("some_future_category".to_string())
7203 );
7204
7205 let json = serde_json::to_value(&unknown).unwrap();
7207 assert_eq!(json, json!("some_future_category"));
7208 }
7209
7210 #[test]
7211 fn test_session_config_option_category_custom_categories() {
7212 let custom: SessionConfigOptionCategory =
7214 serde_json::from_str("\"_my_custom_category\"").unwrap();
7215 assert_eq!(
7216 custom,
7217 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
7218 );
7219
7220 let json = serde_json::to_value(&custom).unwrap();
7222 assert_eq!(json, json!("_my_custom_category"));
7223
7224 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
7226 assert_eq!(
7227 deserialized,
7228 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
7229 );
7230 }
7231
7232 #[test]
7233 fn test_auth_method_agent_serialization() {
7234 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
7235
7236 let json = serde_json::to_value(&method).unwrap();
7237 assert_eq!(
7238 json,
7239 json!({
7240 "id": "default-auth",
7241 "name": "Default Auth"
7242 })
7243 );
7244 assert!(!json.as_object().unwrap().contains_key("description"));
7246 assert!(!json.as_object().unwrap().contains_key("type"));
7248
7249 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7250 match deserialized {
7251 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
7252 assert_eq!(id.0.as_ref(), "default-auth");
7253 assert_eq!(name, "Default Auth");
7254 }
7255 _ => panic!("Expected Agent variant"),
7256 }
7257 }
7258
7259 #[test]
7260 fn test_auth_method_explicit_agent_deserialization() {
7261 let json = json!({
7263 "id": "agent-auth",
7264 "name": "Agent Auth",
7265 "type": "agent"
7266 });
7267
7268 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7269 assert!(matches!(deserialized, AuthMethod::Agent(_)));
7270 }
7271
7272 #[test]
7273 fn test_session_delete_serialization() {
7274 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
7275 assert_eq!(
7276 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
7277 "session/delete"
7278 );
7279 assert_eq!(
7280 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
7281 json!({
7282 "sessionId": "sess_abc123"
7283 })
7284 );
7285 assert_eq!(
7286 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
7287 json!({})
7288 );
7289 assert_eq!(
7290 serde_json::to_value(
7291 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
7292 )
7293 .unwrap(),
7294 json!({
7295 "delete": {}
7296 })
7297 );
7298 }
7299 #[cfg(feature = "unstable_session_set_title")]
7300 #[test]
7301 fn test_session_set_title_serialization() {
7302 assert_eq!(AGENT_METHOD_NAMES.session_set_title, "session/set_title");
7303 assert_eq!(
7304 ClientRequest::SetSessionTitleRequest(SetSessionTitleRequest::new(
7305 "sess_abc123",
7306 "Investigate OAuth timeout"
7307 ))
7308 .method(),
7309 "session/set_title"
7310 );
7311 assert_eq!(
7312 serde_json::to_value(SetSessionTitleRequest::new(
7313 "sess_abc123",
7314 "Investigate OAuth timeout"
7315 ))
7316 .unwrap(),
7317 json!({
7318 "sessionId": "sess_abc123",
7319 "title": "Investigate OAuth timeout"
7320 })
7321 );
7322 assert_eq!(
7323 serde_json::to_value(SetSessionTitleResponse::new("Investigate OAuth timeout"))
7324 .unwrap(),
7325 json!({
7326 "title": "Investigate OAuth timeout"
7327 })
7328 );
7329 assert_eq!(
7330 serde_json::to_value(SessionCapabilities::new().title(SessionTitleCapabilities::new()))
7331 .unwrap(),
7332 json!({
7333 "title": {}
7334 })
7335 );
7336 }
7337
7338 #[cfg(feature = "unstable_session_set_title")]
7339 #[test]
7340 fn test_session_set_title_requires_title() {
7341 for params in [
7342 json!({"sessionId": "sess_abc123"}),
7343 json!({"sessionId": "sess_abc123", "title": null}),
7344 json!({"sessionId": "sess_abc123", "title": 42}),
7345 ] {
7346 assert!(serde_json::from_value::<SetSessionTitleRequest>(params).is_err());
7347 }
7348 for result in [json!({}), json!({"title": null})] {
7349 assert!(serde_json::from_value::<SetSessionTitleResponse>(result).is_err());
7350 }
7351 }
7352
7353 #[cfg(feature = "unstable_session_status")]
7354 #[test]
7355 fn test_session_status_serialization() {
7356 assert_eq!(AGENT_METHOD_NAMES.session_status, "session/status");
7357 assert_eq!(
7358 ClientRequest::SessionStatusRequest(SessionStatusRequest::new("sess_abc123")).method(),
7359 "session/status"
7360 );
7361 assert_eq!(
7362 serde_json::to_value(SessionStatusRequest::new("sess_abc123")).unwrap(),
7363 json!({"sessionId": "sess_abc123"})
7364 );
7365 assert_eq!(
7366 serde_json::to_value(SessionStatusResponse::new(SessionStatus::Saved)).unwrap(),
7367 json!({"status": "saved"})
7368 );
7369 assert_eq!(
7370 serde_json::to_value(
7371 SessionCapabilities::new().status(SessionStatusCapabilities::new())
7372 )
7373 .unwrap(),
7374 json!({"status": {}})
7375 );
7376 }
7377
7378 #[cfg(feature = "unstable_session_status")]
7379 #[test]
7380 fn test_session_status_is_strict_and_open() {
7381 let custom =
7382 serde_json::from_value::<SessionStatusResponse>(json!({"status": "_suspended"}))
7383 .unwrap();
7384 assert_eq!(
7385 custom.status,
7386 SessionStatus::Other("_suspended".to_string())
7387 );
7388 assert_eq!(
7389 serde_json::to_value(&custom).unwrap(),
7390 json!({"status": "_suspended"})
7391 );
7392 for result in [json!({}), json!({"status": null}), json!({"status": 1})] {
7393 assert!(serde_json::from_value::<SessionStatusResponse>(result).is_err());
7394 }
7395 for params in [json!({}), json!({"sessionId": null})] {
7396 assert!(serde_json::from_value::<SessionStatusRequest>(params).is_err());
7397 }
7398 }
7399
7400 #[cfg(feature = "unstable_session_archive")]
7401 #[test]
7402 fn test_session_archive_serialization() {
7403 assert_eq!(AGENT_METHOD_NAMES.session_archive, "session/archive");
7404 assert_eq!(AGENT_METHOD_NAMES.session_unarchive, "session/unarchive");
7405 assert_eq!(
7406 ClientRequest::ArchiveSessionRequest(ArchiveSessionRequest::new("sess_abc123"))
7407 .method(),
7408 "session/archive"
7409 );
7410 assert_eq!(
7411 ClientRequest::UnarchiveSessionRequest(UnarchiveSessionRequest::new("sess_abc123"))
7412 .method(),
7413 "session/unarchive"
7414 );
7415 assert_eq!(
7416 serde_json::to_value(ArchiveSessionRequest::new("sess_abc123")).unwrap(),
7417 json!({"sessionId": "sess_abc123"})
7418 );
7419 assert_eq!(
7420 serde_json::to_value(UnarchiveSessionResponse::new()).unwrap(),
7421 json!({})
7422 );
7423 assert_eq!(
7424 serde_json::to_value(
7425 SessionCapabilities::new().archive(SessionArchiveCapabilities::new())
7426 )
7427 .unwrap(),
7428 json!({"archive": {}})
7429 );
7430 assert_eq!(
7431 serde_json::to_value(
7432 ListSessionsRequest::new()
7433 .cwd("/home/user/project")
7434 .archived(SessionArchiveFilter::Only)
7435 )
7436 .unwrap(),
7437 json!({"cwd": "/home/user/project", "archived": "only"})
7438 );
7439 assert_eq!(
7440 serde_json::to_value(
7441 SessionInfo::new("sess_abc123", "/home/user/project").archived(true)
7442 )
7443 .unwrap(),
7444 json!({"sessionId": "sess_abc123", "cwd": "/home/user/project", "archived": true})
7445 );
7446 }
7447
7448 #[cfg(feature = "unstable_session_archive")]
7449 #[test]
7450 fn test_session_archive_filter_is_strict_and_open() {
7451 for (value, expected) in [
7452 (json!(null), None),
7453 (json!("include"), Some(SessionArchiveFilter::Include)),
7454 (
7455 json!("_recent"),
7456 Some(SessionArchiveFilter::Other("_recent".to_string())),
7457 ),
7458 ] {
7459 let request =
7460 serde_json::from_value::<ListSessionsRequest>(json!({"archived": value})).unwrap();
7461 assert_eq!(request.archived, expected);
7462 }
7463 for value in [json!(true), json!(1), json!({})] {
7464 assert!(
7465 serde_json::from_value::<ListSessionsRequest>(json!({"archived": value})).is_err()
7466 );
7467 }
7468 let info = serde_json::from_value::<SessionInfo>(
7469 json!({"sessionId": "sess_abc123", "cwd": "/home/user/project", "archived": "yes"}),
7470 )
7471 .unwrap();
7472 assert_eq!(info.archived, None);
7473 }
7474
7475 #[test]
7476 fn test_session_additional_directories_serialization() {
7477 assert_eq!(
7478 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
7479 json!({
7480 "cwd": "/home/user/project",
7481 "mcpServers": []
7482 })
7483 );
7484 assert_eq!(
7485 serde_json::to_value(
7486 NewSessionRequest::new("/home/user/project").additional_directories(vec![
7487 PathBuf::from("/home/user/shared-lib"),
7488 PathBuf::from("/home/user/product-docs"),
7489 ])
7490 )
7491 .unwrap(),
7492 json!({
7493 "cwd": "/home/user/project",
7494 "additionalDirectories": [
7495 "/home/user/shared-lib",
7496 "/home/user/product-docs"
7497 ],
7498 "mcpServers": []
7499 })
7500 );
7501 assert_eq!(
7502 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
7503 json!({
7504 "sessionId": "sess_abc123",
7505 "cwd": "/home/user/project"
7506 })
7507 );
7508 assert_eq!(
7509 serde_json::to_value(
7510 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
7511 PathBuf::from("/home/user/shared-lib"),
7512 PathBuf::from("/home/user/product-docs"),
7513 ])
7514 )
7515 .unwrap(),
7516 json!({
7517 "sessionId": "sess_abc123",
7518 "cwd": "/home/user/project",
7519 "additionalDirectories": [
7520 "/home/user/shared-lib",
7521 "/home/user/product-docs"
7522 ]
7523 })
7524 );
7525 assert_eq!(
7526 serde_json::from_value::<SessionInfo>(json!({
7527 "sessionId": "sess_abc123",
7528 "cwd": "/home/user/project"
7529 }))
7530 .unwrap()
7531 .additional_directories,
7532 Vec::<PathBuf>::new()
7533 );
7534 }
7535 #[test]
7536 fn test_session_additional_directories_capabilities_serialization() {
7537 assert_eq!(
7538 serde_json::to_value(
7539 SessionCapabilities::new()
7540 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
7541 )
7542 .unwrap(),
7543 json!({
7544 "additionalDirectories": {}
7545 })
7546 );
7547 }
7548
7549 #[cfg(feature = "unstable_session_system_prompt")]
7550 #[test]
7551 fn test_session_system_prompt_capabilities_serialization() {
7552 assert_eq!(
7553 serde_json::to_value(
7554 SessionCapabilities::new().system_prompt(SessionSystemPromptCapabilities::new())
7555 )
7556 .unwrap(),
7557 json!({ "systemPrompt": {} })
7558 );
7559 assert_eq!(
7560 serde_json::to_value(
7561 SessionCapabilities::new().system_prompt(
7562 SessionSystemPromptCapabilities::new().mode(
7563 SessionSystemPromptModeCapabilities::new()
7564 .override_(SessionSystemPromptOverrideCapabilities::new())
7565 )
7566 )
7567 )
7568 .unwrap(),
7569 json!({ "systemPrompt": { "mode": { "override": {} } } })
7570 );
7571 assert_eq!(
7572 serde_json::from_value::<SessionCapabilities>(
7573 json!({ "systemPrompt": { "mode": { "override": {} } } })
7574 )
7575 .unwrap()
7576 .system_prompt
7577 .and_then(|capabilities| capabilities.mode)
7578 .and_then(|mode| mode.override_),
7579 Some(SessionSystemPromptOverrideCapabilities::new())
7580 );
7581
7582 assert_eq!(
7584 serde_json::from_value::<SessionCapabilities>(json!({ "systemPrompt": "yes" }))
7585 .unwrap()
7586 .system_prompt,
7587 None
7588 );
7589 assert_eq!(
7590 serde_json::from_value::<SessionCapabilities>(
7591 json!({ "systemPrompt": { "mode": { "override": true } } })
7592 )
7593 .unwrap()
7594 .system_prompt,
7595 Some(
7596 SessionSystemPromptCapabilities::new()
7597 .mode(SessionSystemPromptModeCapabilities::new())
7598 )
7599 );
7600 assert_eq!(
7601 serde_json::from_value::<SessionCapabilities>(
7602 json!({ "systemPrompt": { "mode": "override" } })
7603 )
7604 .unwrap()
7605 .system_prompt,
7606 Some(SessionSystemPromptCapabilities::new())
7607 );
7608 }
7609
7610 #[cfg(feature = "unstable_session_system_prompt")]
7611 #[test]
7612 fn test_system_prompt_lifecycle_request_serialization() {
7613 let system_prompt = SystemPrompt::new(vec![ContentBlock::from(
7614 "You are a code review specialist.",
7615 )]);
7616 let system_prompt_json = json!({
7617 "mode": "append",
7618 "content": [{ "type": "text", "text": "You are a code review specialist." }]
7619 });
7620
7621 let request =
7622 NewSessionRequest::new("/home/user/project").system_prompt(system_prompt.clone());
7623 let request_json = json!({
7624 "cwd": "/home/user/project",
7625 "mcpServers": [],
7626 "systemPrompt": system_prompt_json
7627 });
7628 assert_eq!(serde_json::to_value(&request).unwrap(), request_json);
7629 assert_eq!(
7630 serde_json::from_value::<NewSessionRequest>(request_json).unwrap(),
7631 request
7632 );
7633
7634 assert_eq!(
7635 serde_json::to_value(
7636 LoadSessionRequest::new("sess_abc123", "/home/user/project")
7637 .system_prompt(system_prompt.clone())
7638 )
7639 .unwrap()["systemPrompt"],
7640 system_prompt_json
7641 );
7642 assert_eq!(
7643 serde_json::to_value(
7644 ResumeSessionRequest::new("sess_abc123", "/home/user/project")
7645 .system_prompt(system_prompt.clone())
7646 )
7647 .unwrap()["systemPrompt"],
7648 system_prompt_json
7649 );
7650 #[cfg(feature = "unstable_session_fork")]
7651 assert_eq!(
7652 serde_json::to_value(
7653 ForkSessionRequest::new("sess_abc123", "/home/user/project")
7654 .system_prompt(system_prompt.clone())
7655 )
7656 .unwrap()["systemPrompt"],
7657 system_prompt_json
7658 );
7659
7660 let override_prompt =
7661 SystemPrompt::new(vec![ContentBlock::from("...")]).mode(SystemPromptMode::Override);
7662 let override_json = json!({
7663 "mode": "override",
7664 "content": [{ "type": "text", "text": "..." }]
7665 });
7666 assert_eq!(
7667 serde_json::to_value(&override_prompt).unwrap(),
7668 override_json
7669 );
7670 assert_eq!(
7671 serde_json::from_value::<SystemPrompt>(override_json).unwrap(),
7672 override_prompt
7673 );
7674 }
7675
7676 #[cfg(feature = "unstable_session_system_prompt")]
7679 #[test]
7680 fn test_system_prompt_new_defaults_to_append() {
7681 let system_prompt = SystemPrompt::new(vec![ContentBlock::from("...")]);
7682 assert_eq!(system_prompt.mode, SystemPromptMode::Append);
7683 assert_eq!(
7684 serde_json::to_value(&system_prompt).unwrap(),
7685 json!({ "mode": "append", "content": [{ "type": "text", "text": "..." }] })
7686 );
7687 }
7688
7689 #[cfg(feature = "unstable_session_system_prompt")]
7693 #[test]
7694 fn test_system_prompt_preserves_unknown_modes() {
7695 for mode in ["_vendor_mode", "prepend"] {
7696 let system_prompt_json =
7697 json!({ "mode": mode, "content": [{ "type": "text", "text": "..." }] });
7698 let system_prompt: SystemPrompt =
7699 serde_json::from_value(system_prompt_json.clone()).unwrap();
7700 assert_eq!(
7701 system_prompt.mode,
7702 SystemPromptMode::Other(mode.to_string())
7703 );
7704 assert_eq!(
7705 serde_json::to_value(&system_prompt).unwrap(),
7706 system_prompt_json
7707 );
7708 }
7709 }
7710
7711 #[cfg(feature = "unstable_session_system_prompt")]
7715 fn assert_system_prompt_is_strict<T>(base: &serde_json::Value)
7716 where
7717 T: serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
7718 {
7719 let name = std::any::type_name::<T>();
7720 let with = |system_prompt: serde_json::Value| {
7721 let mut request = base.clone();
7722 request["systemPrompt"] = system_prompt;
7723 serde_json::from_value::<T>(request)
7724 };
7725
7726 for system_prompt in [
7727 json!("You are a code review specialist."),
7728 json!({ "content": [{ "type": "text", "text": "..." }] }),
7729 json!({ "mode": null, "content": [{ "type": "text", "text": "..." }] }),
7730 json!({ "mode": 1, "content": [{ "type": "text", "text": "..." }] }),
7731 json!({ "mode": "append" }),
7732 json!({ "mode": "append", "content": "..." }),
7733 json!({ "mode": "append", "content": [{ "type": "text" }] }),
7734 json!({ "mode": "append", "content": [{ "type": "video", "uri": "..." }] }),
7735 ] {
7736 assert!(
7737 with(system_prompt.clone()).is_err(),
7738 "{name}.systemPrompt: {system_prompt}"
7739 );
7740 }
7741
7742 assert_eq!(
7743 with(serde_json::Value::Null).unwrap(),
7744 serde_json::from_value::<T>(base.clone()).unwrap(),
7745 "{name}.systemPrompt"
7746 );
7747 }
7748
7749 #[cfg(feature = "unstable_session_system_prompt")]
7750 #[test]
7751 fn test_session_setup_requests_reject_malformed_system_prompts() {
7752 assert!(
7753 serde_json::to_value(NewSessionRequest::new("/repo"))
7754 .unwrap()
7755 .get("systemPrompt")
7756 .is_none()
7757 );
7758 assert_system_prompt_is_strict::<NewSessionRequest>(&json!({
7759 "cwd": "/repo",
7760 "mcpServers": []
7761 }));
7762 assert_system_prompt_is_strict::<LoadSessionRequest>(&json!({
7763 "sessionId": "sess-1",
7764 "cwd": "/repo",
7765 "mcpServers": []
7766 }));
7767 assert_system_prompt_is_strict::<ResumeSessionRequest>(&json!({
7768 "sessionId": "sess-1",
7769 "cwd": "/repo"
7770 }));
7771 #[cfg(feature = "unstable_session_fork")]
7772 assert_system_prompt_is_strict::<ForkSessionRequest>(&json!({
7773 "sessionId": "sess-1",
7774 "cwd": "/repo"
7775 }));
7776 }
7777
7778 #[test]
7779 fn test_auth_method_terminal_serialization() {
7780 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
7781
7782 let json = serde_json::to_value(&method).unwrap();
7783 assert_eq!(
7784 json,
7785 json!({
7786 "id": "tui-auth",
7787 "name": "Terminal Auth",
7788 "type": "terminal"
7789 })
7790 );
7791 assert!(!json.as_object().unwrap().contains_key("args"));
7793 assert!(!json.as_object().unwrap().contains_key("env"));
7794
7795 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7796 match deserialized {
7797 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
7798 assert_eq!(args, Vec::<String>::new());
7799 assert!(env.is_empty());
7800 }
7801 _ => panic!("Expected Terminal variant"),
7802 }
7803 }
7804
7805 #[test]
7806 fn test_auth_method_terminal_with_args_and_env_serialization() {
7807 use std::collections::HashMap;
7808
7809 let mut env = HashMap::new();
7810 env.insert("TERM".to_string(), "xterm-256color".to_string());
7811
7812 let method = AuthMethod::Terminal(
7813 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
7814 .args(vec!["--interactive".to_string(), "--color".to_string()])
7815 .env(env),
7816 );
7817
7818 let json = serde_json::to_value(&method).unwrap();
7819 assert_eq!(
7820 json,
7821 json!({
7822 "id": "tui-auth",
7823 "name": "Terminal Auth",
7824 "type": "terminal",
7825 "args": ["--interactive", "--color"],
7826 "env": {
7827 "TERM": "xterm-256color"
7828 }
7829 })
7830 );
7831
7832 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
7833 match deserialized {
7834 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
7835 assert_eq!(args, vec!["--interactive", "--color"]);
7836 assert_eq!(env.len(), 1);
7837 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
7838 }
7839 _ => panic!("Expected Terminal variant"),
7840 }
7841 }
7842
7843 #[test]
7844 fn test_session_config_option_value_id_serialize() {
7845 let val = SessionConfigOptionValue::value_id("model-1");
7846 let json = serde_json::to_value(&val).unwrap();
7847 assert_eq!(json, json!({ "value": "model-1" }));
7849 assert!(!json.as_object().unwrap().contains_key("type"));
7850 }
7851
7852 #[test]
7853 fn test_session_config_option_value_boolean_serialize() {
7854 let val = SessionConfigOptionValue::boolean(true);
7855 let json = serde_json::to_value(&val).unwrap();
7856 assert_eq!(json, json!({ "type": "boolean", "value": true }));
7857 }
7858
7859 #[test]
7860 fn test_session_config_option_value_deserialize_no_type() {
7861 let json = json!({ "value": "model-1" });
7863 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7864 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
7865 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
7866 }
7867
7868 #[test]
7869 fn test_session_config_option_value_deserialize_boolean() {
7870 let json = json!({ "type": "boolean", "value": true });
7871 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7872 assert_eq!(val, SessionConfigOptionValue::boolean(true));
7873 assert_eq!(val.as_bool(), Some(true));
7874 }
7875
7876 #[test]
7877 fn test_session_config_option_value_deserialize_boolean_false() {
7878 let json = json!({ "type": "boolean", "value": false });
7879 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7880 assert_eq!(val, SessionConfigOptionValue::boolean(false));
7881 assert_eq!(val.as_bool(), Some(false));
7882 }
7883
7884 #[test]
7885 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
7886 let json = json!({ "type": "text", "value": "freeform input" });
7888 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7889 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
7890 }
7891
7892 #[test]
7893 fn test_session_config_option_value_roundtrip_value_id() {
7894 let original = SessionConfigOptionValue::value_id("option-a");
7895 let json = serde_json::to_value(&original).unwrap();
7896 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7897 assert_eq!(original, roundtripped);
7898 }
7899
7900 #[test]
7901 fn test_session_config_option_value_roundtrip_boolean() {
7902 let original = SessionConfigOptionValue::boolean(false);
7903 let json = serde_json::to_value(&original).unwrap();
7904 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
7905 assert_eq!(original, roundtripped);
7906 }
7907
7908 #[test]
7909 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
7910 let json = json!({ "type": "boolean", "value": "not a bool" });
7912 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
7913 assert!(result.is_ok());
7915 assert_eq!(
7916 result.unwrap().as_value_id().unwrap().to_string(),
7917 "not a bool"
7918 );
7919 }
7920
7921 #[test]
7922 fn test_session_config_option_value_from_impls() {
7923 let from_str: SessionConfigOptionValue = "model-1".into();
7924 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
7925
7926 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
7927 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
7928
7929 let from_bool: SessionConfigOptionValue = true.into();
7930 assert_eq!(from_bool.as_bool(), Some(true));
7931 }
7932
7933 #[test]
7934 fn test_set_session_config_option_request_value_id() {
7935 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
7936 let json = serde_json::to_value(&req).unwrap();
7937 assert_eq!(
7938 json,
7939 json!({
7940 "sessionId": "sess_1",
7941 "configId": "model",
7942 "value": "model-1"
7943 })
7944 );
7945 assert!(!json.as_object().unwrap().contains_key("type"));
7947 }
7948
7949 #[test]
7950 fn test_set_session_config_option_request_boolean() {
7951 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
7952 let json = serde_json::to_value(&req).unwrap();
7953 assert_eq!(
7954 json,
7955 json!({
7956 "sessionId": "sess_1",
7957 "configId": "brave_mode",
7958 "type": "boolean",
7959 "value": true
7960 })
7961 );
7962 }
7963
7964 #[test]
7965 fn test_set_session_config_option_request_deserialize_no_type() {
7966 let json = json!({
7968 "sessionId": "sess_1",
7969 "configId": "model",
7970 "value": "model-1"
7971 });
7972 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7973 assert_eq!(req.session_id.to_string(), "sess_1");
7974 assert_eq!(req.config_id.to_string(), "model");
7975 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
7976 }
7977
7978 #[test]
7979 fn test_set_session_config_option_request_deserialize_boolean() {
7980 let json = json!({
7981 "sessionId": "sess_1",
7982 "configId": "brave_mode",
7983 "type": "boolean",
7984 "value": true
7985 });
7986 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7987 assert_eq!(req.value.as_bool(), Some(true));
7988 }
7989
7990 #[test]
7991 fn test_set_session_config_option_request_roundtrip_value_id() {
7992 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
7993 let json = serde_json::to_value(&original).unwrap();
7994 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
7995 assert_eq!(original, roundtripped);
7996 }
7997
7998 #[test]
7999 fn test_set_session_config_option_request_roundtrip_boolean() {
8000 let original = SetSessionConfigOptionRequest::new("s", "c", false);
8001 let json = serde_json::to_value(&original).unwrap();
8002 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
8003 assert_eq!(original, roundtripped);
8004 }
8005
8006 #[test]
8007 fn test_session_config_boolean_serialization() {
8008 let cfg = SessionConfigBoolean::new(true);
8009 let json = serde_json::to_value(&cfg).unwrap();
8010 assert_eq!(json, json!({ "currentValue": true }));
8011
8012 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
8013 assert!(deserialized.current_value);
8014 }
8015
8016 #[test]
8017 fn test_session_config_option_boolean_variant() {
8018 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
8019 .description("Skip confirmation prompts")
8020 .meta(test_meta());
8021 assert_eq!(serialized_meta_key_count(&opt), 1);
8022
8023 let json = serde_json::to_value(&opt).unwrap();
8024 assert_eq!(
8025 json,
8026 json!({
8027 "id": "brave_mode",
8028 "name": "Brave Mode",
8029 "description": "Skip confirmation prompts",
8030 "type": "boolean",
8031 "currentValue": false,
8032 "_meta": {
8033 "source": "test"
8034 }
8035 })
8036 );
8037
8038 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
8039 assert_eq!(deserialized.id.to_string(), "brave_mode");
8040 assert_eq!(deserialized.name, "Brave Mode");
8041 match deserialized.kind {
8042 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
8043 _ => panic!("Expected Boolean kind"),
8044 }
8045 }
8046
8047 #[test]
8048 fn test_session_config_option_select_still_works() {
8049 let opt = SessionConfigOption::select(
8051 "model",
8052 "Model",
8053 "model-1",
8054 vec![
8055 SessionConfigSelectOption::new("model-1", "Model 1"),
8056 SessionConfigSelectOption::new("model-2", "Model 2"),
8057 ],
8058 )
8059 .meta(test_meta());
8060 assert_eq!(serialized_meta_key_count(&opt), 1);
8061
8062 let json = serde_json::to_value(&opt).unwrap();
8063 assert_eq!(json["type"], "select");
8064 assert_eq!(json["currentValue"], "model-1");
8065 assert_eq!(json["options"].as_array().unwrap().len(), 2);
8066 assert_eq!(json["_meta"]["source"], "test");
8067
8068 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
8069 match deserialized.kind {
8070 SessionConfigKind::Select(ref s) => {
8071 assert_eq!(s.current_value.to_string(), "model-1");
8072 }
8073 _ => panic!("Expected Select kind"),
8074 }
8075 }
8076
8077 #[cfg(feature = "unstable_llm_providers")]
8078 #[test]
8079 fn test_llm_protocol_known_variants() {
8080 assert_eq!(
8081 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
8082 json!("anthropic")
8083 );
8084 assert_eq!(
8085 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
8086 json!("openai")
8087 );
8088 assert_eq!(
8089 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
8090 json!("azure")
8091 );
8092 assert_eq!(
8093 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
8094 json!("vertex")
8095 );
8096 assert_eq!(
8097 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
8098 json!("bedrock")
8099 );
8100
8101 assert_eq!(
8102 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
8103 LlmProtocol::Anthropic
8104 );
8105 assert_eq!(
8106 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
8107 LlmProtocol::OpenAi
8108 );
8109 assert_eq!(
8110 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
8111 LlmProtocol::Azure
8112 );
8113 assert_eq!(
8114 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
8115 LlmProtocol::Vertex
8116 );
8117 assert_eq!(
8118 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
8119 LlmProtocol::Bedrock
8120 );
8121 }
8122
8123 #[cfg(feature = "unstable_llm_providers")]
8124 #[test]
8125 fn test_llm_protocol_unknown_variant() {
8126 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
8127 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
8128
8129 let json = serde_json::to_value(&unknown).unwrap();
8130 assert_eq!(json, json!("cohere"));
8131 }
8132
8133 #[cfg(feature = "unstable_llm_providers")]
8134 #[test]
8135 fn test_provider_current_config_serialization() {
8136 let config =
8137 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
8138
8139 let json = serde_json::to_value(&config).unwrap();
8140 assert_eq!(
8141 json,
8142 json!({
8143 "apiType": "anthropic",
8144 "baseUrl": "https://api.anthropic.com"
8145 })
8146 );
8147
8148 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
8149 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
8150 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
8151 }
8152
8153 #[cfg(feature = "unstable_llm_providers")]
8154 #[test]
8155 fn test_provider_info_with_current_config() {
8156 let info = ProviderInfo::new(
8157 "main",
8158 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
8159 true,
8160 Some(ProviderCurrentConfig::new(
8161 LlmProtocol::Anthropic,
8162 "https://api.anthropic.com",
8163 )),
8164 );
8165
8166 let json = serde_json::to_value(&info).unwrap();
8167 assert_eq!(
8168 json,
8169 json!({
8170 "providerId": "main",
8171 "supported": ["anthropic", "openai"],
8172 "required": true,
8173 "current": {
8174 "apiType": "anthropic",
8175 "baseUrl": "https://api.anthropic.com"
8176 }
8177 })
8178 );
8179
8180 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8181 assert_eq!(deserialized.provider_id.to_string(), "main");
8182 assert_eq!(deserialized.supported.len(), 2);
8183 assert!(deserialized.required);
8184 assert!(deserialized.current.is_some());
8185 assert_eq!(
8186 deserialized.current.as_ref().unwrap().api_type,
8187 LlmProtocol::Anthropic
8188 );
8189 }
8190
8191 #[cfg(feature = "unstable_llm_providers")]
8192 #[test]
8193 fn test_provider_info_disabled() {
8194 let info = ProviderInfo::new(
8195 "secondary",
8196 vec![LlmProtocol::OpenAi],
8197 false,
8198 None::<ProviderCurrentConfig>,
8199 );
8200
8201 let json = serde_json::to_value(&info).unwrap();
8202 assert_eq!(
8203 json,
8204 json!({
8205 "providerId": "secondary",
8206 "supported": ["openai"],
8207 "required": false
8208 })
8209 );
8210
8211 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8212 assert_eq!(deserialized.provider_id.to_string(), "secondary");
8213 assert!(!deserialized.required);
8214 assert!(deserialized.current.is_none());
8215 }
8216
8217 #[cfg(feature = "unstable_llm_providers")]
8218 #[test]
8219 fn test_provider_info_missing_current_defaults_to_none() {
8220 let json = json!({
8222 "providerId": "main",
8223 "supported": ["anthropic"],
8224 "required": true
8225 });
8226 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8227 assert!(deserialized.current.is_none());
8228 }
8229
8230 #[cfg(feature = "unstable_llm_providers")]
8231 #[test]
8232 fn test_provider_info_explicit_null_current_decodes_to_none() {
8233 let json = json!({
8237 "providerId": "main",
8238 "supported": ["anthropic"],
8239 "required": true,
8240 "current": null
8241 });
8242 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
8243 assert!(deserialized.current.is_none());
8244 }
8245
8246 #[cfg(feature = "unstable_llm_providers")]
8247 #[test]
8248 fn test_list_providers_response_serialization() {
8249 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
8250 "main",
8251 vec![LlmProtocol::Anthropic],
8252 true,
8253 Some(ProviderCurrentConfig::new(
8254 LlmProtocol::Anthropic,
8255 "https://api.anthropic.com",
8256 )),
8257 )]);
8258
8259 let json = serde_json::to_value(&response).unwrap();
8260 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
8261 assert_eq!(json["providers"][0]["providerId"], "main");
8262
8263 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
8264 assert_eq!(deserialized.providers.len(), 1);
8265 }
8266
8267 #[cfg(feature = "unstable_llm_providers")]
8268 #[test]
8269 fn test_set_provider_request_serialization() {
8270 use std::collections::HashMap;
8271
8272 let mut headers = HashMap::new();
8273 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
8274
8275 let request =
8276 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
8277 .headers(headers);
8278
8279 let json = serde_json::to_value(&request).unwrap();
8280 assert_eq!(
8281 json,
8282 json!({
8283 "providerId": "main",
8284 "apiType": "openai",
8285 "baseUrl": "https://api.openai.com/v1",
8286 "headers": {
8287 "Authorization": "Bearer sk-test"
8288 }
8289 })
8290 );
8291
8292 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
8293 assert_eq!(deserialized.provider_id.to_string(), "main");
8294 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
8295 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
8296 assert_eq!(deserialized.headers.len(), 1);
8297 assert_eq!(
8298 deserialized.headers.get("Authorization").unwrap(),
8299 "Bearer sk-test"
8300 );
8301 }
8302
8303 #[cfg(feature = "unstable_llm_providers")]
8304 #[test]
8305 fn test_set_provider_request_omits_empty_headers() {
8306 let request =
8307 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
8308
8309 let json = serde_json::to_value(&request).unwrap();
8310 assert!(!json.as_object().unwrap().contains_key("headers"));
8312 }
8313
8314 #[cfg(feature = "unstable_llm_providers")]
8315 #[test]
8316 fn test_disable_provider_request_serialization() {
8317 let request = DisableProviderRequest::new("secondary");
8318
8319 let json = serde_json::to_value(&request).unwrap();
8320 assert_eq!(json, json!({ "providerId": "secondary" }));
8321
8322 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
8323 assert_eq!(deserialized.provider_id.to_string(), "secondary");
8324 }
8325
8326 #[cfg(feature = "unstable_llm_providers")]
8327 #[test]
8328 fn test_providers_capabilities_serialization() {
8329 let caps = ProvidersCapabilities::new();
8330
8331 let json = serde_json::to_value(&caps).unwrap();
8332 assert_eq!(json, json!({}));
8333
8334 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
8335 assert!(deserialized.meta.is_none());
8336 }
8337
8338 #[cfg(feature = "unstable_llm_providers")]
8339 #[test]
8340 fn test_agent_capabilities_with_providers() {
8341 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
8342
8343 let json = serde_json::to_value(&caps).unwrap();
8344 assert_eq!(json["providers"], json!({}));
8345
8346 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
8347 assert!(deserialized.providers.is_some());
8348 }
8349
8350 #[test]
8351 fn prompt_request_rejects_malformed_content_block() {
8352 use serde_json::json;
8353
8354 assert!(
8355 serde_json::from_value::<PromptRequest>(json!({
8356 "sessionId": "sess-1",
8357 "prompt": [{"type": "text"}]
8358 }))
8359 .is_err()
8360 );
8361 }
8362
8363 #[test]
8364 fn prompt_request_rejects_non_array_prompt() {
8365 use serde_json::json;
8366
8367 assert!(
8368 serde_json::from_value::<PromptRequest>(json!({
8369 "sessionId": "sess-1",
8370 "prompt": "hello"
8371 }))
8372 .is_err()
8373 );
8374 }
8375
8376 fn assert_session_setup_lists_are_strict<T>(base: &serde_json::Value)
8377 where
8378 T: serde::de::DeserializeOwned + PartialEq + std::fmt::Debug,
8379 {
8380 let name = std::any::type_name::<T>();
8381 let with = |field: &str, value: serde_json::Value| {
8382 let mut request = base.clone();
8383 request[field] = value;
8384 serde_json::from_value::<T>(request)
8385 };
8386
8387 for (field, value) in [
8388 (
8390 "mcpServers",
8391 json!([
8392 {"name": "github", "command": "/usr/bin/gh-mcp", "args": [], "env": [{"name": "GITHUB_TOKEN", "value": null}]},
8393 {"name": "fs", "command": "/usr/bin/fs-mcp", "args": [], "env": []}
8394 ]),
8395 ),
8396 ("mcpServers", json!({"name": "fs"})),
8397 ("additionalDirectories", json!(["/repo/lib", 42])),
8398 ("additionalDirectories", json!("/repo/lib")),
8399 ] {
8400 assert!(
8401 with(field, value.clone()).is_err(),
8402 "{name}.{field}: {value}"
8403 );
8404 }
8405
8406 let empty = serde_json::from_value::<T>(base.clone()).unwrap();
8407 for field in ["mcpServers", "additionalDirectories"] {
8408 assert_eq!(
8409 with(field, serde_json::Value::Null).unwrap(),
8410 empty,
8411 "{name}.{field}"
8412 );
8413 }
8414 }
8415
8416 #[test]
8417 fn session_setup_requests_reject_malformed_mcp_servers_and_directories() {
8418 assert_session_setup_lists_are_strict::<NewSessionRequest>(&json!({
8419 "cwd": "/repo",
8420 "mcpServers": []
8421 }));
8422 assert_session_setup_lists_are_strict::<LoadSessionRequest>(&json!({
8423 "sessionId": "sess-1",
8424 "cwd": "/repo",
8425 "mcpServers": []
8426 }));
8427 assert_session_setup_lists_are_strict::<ResumeSessionRequest>(&json!({
8428 "sessionId": "sess-1",
8429 "cwd": "/repo"
8430 }));
8431 #[cfg(feature = "unstable_session_fork")]
8432 assert_session_setup_lists_are_strict::<ForkSessionRequest>(&json!({
8433 "sessionId": "sess-1",
8434 "cwd": "/repo"
8435 }));
8436 }
8437
8438 #[test]
8439 fn mcp_server_lists_treat_null_as_empty() {
8440 let servers: Vec<McpServer> = serde_json::from_value(json!([
8441 {"name": "fs", "command": "/usr/bin/fs-mcp", "args": null, "env": null},
8442 {"type": "http", "name": "api", "url": "https://example.com/mcp", "headers": null},
8443 {"type": "sse", "name": "events", "url": "https://example.com/sse", "headers": null}
8444 ]))
8445 .unwrap();
8446
8447 assert_eq!(
8448 servers,
8449 vec![
8450 McpServer::Stdio(McpServerStdio::new("fs", "/usr/bin/fs-mcp")),
8451 McpServer::Http(McpServerHttp::new("api", "https://example.com/mcp")),
8452 McpServer::Sse(McpServerSse::new("events", "https://example.com/sse")),
8453 ]
8454 );
8455 }
8456
8457 #[test]
8458 fn terminal_auth_methods_reject_malformed_launch_config() {
8459 let response: InitializeResponse = serde_json::from_value(json!({
8463 "protocolVersion": 1,
8464 "authMethods": [
8465 {"type": "terminal", "id": "bad-args", "name": "Log in", "args": ["auth", "--port", 8123]},
8466 {"type": "terminal", "id": "bad-env", "name": "Log in", "env": {"AUTH_MODE": "device", "DEBUG": 1}},
8467 {"type": "terminal", "id": "null-config", "name": "Log in", "args": null, "env": null},
8468 {"id": "agent", "name": "Agent login"}
8469 ]
8470 }))
8471 .unwrap();
8472
8473 assert_eq!(
8474 response.auth_methods,
8475 vec![
8476 AuthMethod::Terminal(AuthMethodTerminal::new("null-config", "Log in")),
8477 AuthMethod::Agent(AuthMethodAgent::new("agent", "Agent login")),
8478 ]
8479 );
8480 assert!(
8481 serde_json::from_value::<AuthMethod>(json!({
8482 "type": "terminal",
8483 "id": "bad-args",
8484 "name": "Log in",
8485 "args": ["auth", 8123]
8486 }))
8487 .is_err()
8488 );
8489 }
8490
8491 #[cfg(feature = "unstable_auth_status")]
8492 #[test]
8493 fn auth_status_response_round_trips() {
8494 let response = AuthStatusResponse::new(AuthState::Authenticated).accounts(vec![
8495 AuthAccount::new("Anthropic API key").active(true),
8496 AuthAccount::new("Claude Max").email("user@example.com".to_string()),
8497 ]);
8498 let json = serde_json::to_value(&response).unwrap();
8499 assert_eq!(
8500 json,
8501 json!({
8502 "state": "authenticated",
8503 "accounts": [
8504 {
8505 "label": "Anthropic API key",
8506 "active": true
8507 },
8508 {
8509 "label": "Claude Max",
8510 "email": "user@example.com"
8511 }
8512 ]
8513 })
8514 );
8515 assert_eq!(
8516 serde_json::from_value::<AuthStatusResponse>(json).unwrap(),
8517 response
8518 );
8519 assert_eq!(
8520 serde_json::to_value(AuthStatusResponse::new(AuthState::NotRequired)).unwrap(),
8521 json!({"state": "not_required"})
8522 );
8523 }
8524
8525 #[cfg(feature = "unstable_auth_status")]
8526 #[test]
8527 fn auth_status_state_is_strict_and_accounts_are_lenient() {
8528 assert!(serde_json::from_value::<AuthStatusResponse>(json!({})).is_err());
8529 assert!(serde_json::from_value::<AuthStatusResponse>(json!({"state": null})).is_err());
8530 assert!(serde_json::from_value::<AuthStatusResponse>(json!({"state": 1})).is_err());
8531
8532 let response: AuthStatusResponse = serde_json::from_value(json!({
8533 "state": "_vendor_state",
8534 "accounts": [
8535 {"active": true},
8536 {
8537 "label": "Vertex AI",
8538 "active": "yes",
8539 "email": ["not", "a", "string"]
8540 }
8541 ]
8542 }))
8543 .unwrap();
8544 assert_eq!(
8545 response,
8546 AuthStatusResponse::new(AuthState::Other("_vendor_state".to_string()))
8547 .accounts(vec![AuthAccount::new("Vertex AI")])
8548 );
8549 assert_eq!(
8550 serde_json::from_value::<AuthStatusResponse>(
8551 json!({"state": "unknown", "accounts": null})
8552 )
8553 .unwrap(),
8554 AuthStatusResponse::new(AuthState::Unknown)
8555 );
8556 }
8557
8558 #[cfg(feature = "unstable_auth_status")]
8559 #[test]
8560 fn auth_status_update_notification_routes() {
8561 use crate::v1::{AgentNotification, CLIENT_METHOD_NAMES};
8562
8563 assert_eq!(AGENT_METHOD_NAMES.auth_status, "auth/status");
8564 assert_eq!(CLIENT_METHOD_NAMES.auth_status_update, "auth/status_update");
8565 let notification = AgentNotification::AuthStatusUpdateNotification(
8566 AuthStatusUpdateNotification::new(AuthState::Unauthenticated),
8567 );
8568 assert_eq!(notification.method(), "auth/status_update");
8569 assert_eq!(
8570 serde_json::to_value(¬ification).unwrap(),
8571 json!({"state": "unauthenticated"})
8572 );
8573 }
8574}