1use std::{path::PathBuf, sync::Arc};
7
8#[cfg(any(feature = "unstable_auth_methods", feature = "unstable_llm_providers"))]
9use std::collections::HashMap;
10
11use derive_more::{Display, From};
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
15
16#[cfg(feature = "unstable_auth_methods")]
17use crate::DefaultTrueOnError;
18use crate::{IntoOption, ProtocolVersion, SkipListener};
19
20use super::{
21 ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, Meta, SessionId,
22};
23
24#[cfg(feature = "unstable_mcp_over_acp")]
25use super::mcp::{
26 MCP_MESSAGE_METHOD_NAME, MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
27};
28
29#[cfg(feature = "unstable_nes")]
30use super::{
31 AcceptNesNotification, CloseNesRequest, CloseNesResponse, DidChangeDocumentNotification,
32 DidCloseDocumentNotification, DidFocusDocumentNotification, DidOpenDocumentNotification,
33 DidSaveDocumentNotification, NesCapabilities, PositionEncodingKind, RejectNesNotification,
34 StartNesRequest, StartNesResponse, SuggestNesRequest, SuggestNesResponse,
35};
36
37#[cfg(feature = "unstable_nes")]
38use super::{
39 DOCUMENT_DID_CHANGE_METHOD_NAME, DOCUMENT_DID_CLOSE_METHOD_NAME,
40 DOCUMENT_DID_FOCUS_METHOD_NAME, DOCUMENT_DID_OPEN_METHOD_NAME, DOCUMENT_DID_SAVE_METHOD_NAME,
41 NES_ACCEPT_METHOD_NAME, NES_CLOSE_METHOD_NAME, NES_REJECT_METHOD_NAME, NES_START_METHOD_NAME,
42 NES_SUGGEST_METHOD_NAME,
43};
44
45#[serde_as]
53#[skip_serializing_none]
54#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
55#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
56#[serde(rename_all = "camelCase")]
57#[non_exhaustive]
58pub struct InitializeRequest {
59 pub protocol_version: ProtocolVersion,
61 #[serde_as(deserialize_as = "DefaultOnError")]
63 #[schemars(extend("x-deserialize-default-on-error" = true))]
64 #[serde(default)]
65 pub client_capabilities: ClientCapabilities,
66 #[serde_as(deserialize_as = "DefaultOnError")]
70 #[schemars(extend("x-deserialize-default-on-error" = true))]
71 #[serde(default)]
72 pub client_info: Option<Implementation>,
73 #[serde_as(deserialize_as = "DefaultOnError")]
79 #[schemars(extend("x-deserialize-default-on-error" = true))]
80 #[serde(default)]
81 #[serde(rename = "_meta")]
82 pub meta: Option<Meta>,
83}
84
85impl InitializeRequest {
86 #[must_use]
88 pub fn new(protocol_version: ProtocolVersion) -> Self {
89 Self {
90 protocol_version,
91 client_capabilities: ClientCapabilities::default(),
92 client_info: None,
93 meta: None,
94 }
95 }
96
97 #[must_use]
99 pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
100 self.client_capabilities = client_capabilities;
101 self
102 }
103
104 #[must_use]
106 pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
107 self.client_info = client_info.into_option();
108 self
109 }
110
111 #[must_use]
117 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
118 self.meta = meta.into_option();
119 self
120 }
121}
122
123#[serde_as]
129#[skip_serializing_none]
130#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
131#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
132#[serde(rename_all = "camelCase")]
133#[non_exhaustive]
134pub struct InitializeResponse {
135 pub protocol_version: ProtocolVersion,
140 #[serde_as(deserialize_as = "DefaultOnError")]
142 #[schemars(extend("x-deserialize-default-on-error" = true))]
143 #[serde(default)]
144 pub agent_capabilities: AgentCapabilities,
145 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
147 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
148 #[serde(default)]
149 pub auth_methods: Vec<AuthMethod>,
150 #[serde_as(deserialize_as = "DefaultOnError")]
154 #[schemars(extend("x-deserialize-default-on-error" = true))]
155 #[serde(default)]
156 pub agent_info: Option<Implementation>,
157 #[serde_as(deserialize_as = "DefaultOnError")]
163 #[schemars(extend("x-deserialize-default-on-error" = true))]
164 #[serde(default)]
165 #[serde(rename = "_meta")]
166 pub meta: Option<Meta>,
167}
168
169impl InitializeResponse {
170 #[must_use]
172 pub fn new(protocol_version: ProtocolVersion) -> Self {
173 Self {
174 protocol_version,
175 agent_capabilities: AgentCapabilities::default(),
176 auth_methods: vec![],
177 agent_info: None,
178 meta: None,
179 }
180 }
181
182 #[must_use]
184 pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
185 self.agent_capabilities = agent_capabilities;
186 self
187 }
188
189 #[must_use]
191 pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
192 self.auth_methods = auth_methods;
193 self
194 }
195
196 #[must_use]
198 pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
199 self.agent_info = agent_info.into_option();
200 self
201 }
202
203 #[must_use]
209 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
210 self.meta = meta.into_option();
211 self
212 }
213}
214
215#[serde_as]
219#[skip_serializing_none]
220#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
221#[serde(rename_all = "camelCase")]
222#[non_exhaustive]
223pub struct Implementation {
224 pub name: String,
227 #[serde_as(deserialize_as = "DefaultOnError")]
232 #[schemars(extend("x-deserialize-default-on-error" = true))]
233 #[serde(default)]
234 pub title: Option<String>,
235 pub version: String,
238 #[serde_as(deserialize_as = "DefaultOnError")]
244 #[schemars(extend("x-deserialize-default-on-error" = true))]
245 #[serde(default)]
246 #[serde(rename = "_meta")]
247 pub meta: Option<Meta>,
248}
249
250impl Implementation {
251 #[must_use]
253 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
254 Self {
255 name: name.into(),
256 title: None,
257 version: version.into(),
258 meta: None,
259 }
260 }
261
262 #[must_use]
267 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
268 self.title = title.into_option();
269 self
270 }
271
272 #[must_use]
278 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
279 self.meta = meta.into_option();
280 self
281 }
282}
283
284#[serde_as]
290#[skip_serializing_none]
291#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
292#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
293#[serde(rename_all = "camelCase")]
294#[non_exhaustive]
295pub struct AuthenticateRequest {
296 pub method_id: AuthMethodId,
299 #[serde_as(deserialize_as = "DefaultOnError")]
305 #[schemars(extend("x-deserialize-default-on-error" = true))]
306 #[serde(default)]
307 #[serde(rename = "_meta")]
308 pub meta: Option<Meta>,
309}
310
311impl AuthenticateRequest {
312 #[must_use]
314 pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
315 Self {
316 method_id: method_id.into(),
317 meta: None,
318 }
319 }
320
321 #[must_use]
327 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
328 self.meta = meta.into_option();
329 self
330 }
331}
332
333#[serde_as]
335#[skip_serializing_none]
336#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
337#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
338#[serde(rename_all = "camelCase")]
339#[non_exhaustive]
340pub struct AuthenticateResponse {
341 #[serde_as(deserialize_as = "DefaultOnError")]
347 #[schemars(extend("x-deserialize-default-on-error" = true))]
348 #[serde(default)]
349 #[serde(rename = "_meta")]
350 pub meta: Option<Meta>,
351}
352
353impl AuthenticateResponse {
354 #[must_use]
356 pub fn new() -> Self {
357 Self::default()
358 }
359
360 #[must_use]
366 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
367 self.meta = meta.into_option();
368 self
369 }
370}
371
372#[serde_as]
378#[skip_serializing_none]
379#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
380#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
381#[serde(rename_all = "camelCase")]
382#[non_exhaustive]
383pub struct LogoutRequest {
384 #[serde_as(deserialize_as = "DefaultOnError")]
390 #[schemars(extend("x-deserialize-default-on-error" = true))]
391 #[serde(default)]
392 #[serde(rename = "_meta")]
393 pub meta: Option<Meta>,
394}
395
396impl LogoutRequest {
397 #[must_use]
399 pub fn new() -> Self {
400 Self::default()
401 }
402
403 #[must_use]
409 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
410 self.meta = meta.into_option();
411 self
412 }
413}
414
415#[serde_as]
417#[skip_serializing_none]
418#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
419#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
420#[serde(rename_all = "camelCase")]
421#[non_exhaustive]
422pub struct LogoutResponse {
423 #[serde_as(deserialize_as = "DefaultOnError")]
429 #[schemars(extend("x-deserialize-default-on-error" = true))]
430 #[serde(default)]
431 #[serde(rename = "_meta")]
432 pub meta: Option<Meta>,
433}
434
435impl LogoutResponse {
436 #[must_use]
438 pub fn new() -> Self {
439 Self::default()
440 }
441
442 #[must_use]
448 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
449 self.meta = meta.into_option();
450 self
451 }
452}
453
454#[serde_as]
456#[skip_serializing_none]
457#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
458#[serde(rename_all = "camelCase")]
459#[non_exhaustive]
460pub struct AgentAuthCapabilities {
461 #[serde_as(deserialize_as = "DefaultOnError")]
466 #[schemars(extend("x-deserialize-default-on-error" = true))]
467 #[serde(default)]
468 pub logout: Option<LogoutCapabilities>,
469 #[serde_as(deserialize_as = "DefaultOnError")]
475 #[schemars(extend("x-deserialize-default-on-error" = true))]
476 #[serde(default)]
477 #[serde(rename = "_meta")]
478 pub meta: Option<Meta>,
479}
480
481impl AgentAuthCapabilities {
482 #[must_use]
484 pub fn new() -> Self {
485 Self::default()
486 }
487
488 #[must_use]
490 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
491 self.logout = logout.into_option();
492 self
493 }
494
495 #[must_use]
501 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
502 self.meta = meta.into_option();
503 self
504 }
505}
506
507#[serde_as]
511#[skip_serializing_none]
512#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
513#[non_exhaustive]
514pub struct LogoutCapabilities {
515 #[serde_as(deserialize_as = "DefaultOnError")]
521 #[schemars(extend("x-deserialize-default-on-error" = true))]
522 #[serde(default)]
523 #[serde(rename = "_meta")]
524 pub meta: Option<Meta>,
525}
526
527impl LogoutCapabilities {
528 #[must_use]
530 pub fn new() -> Self {
531 Self::default()
532 }
533
534 #[must_use]
540 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
541 self.meta = meta.into_option();
542 self
543 }
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
548#[serde(transparent)]
549#[from(Arc<str>, String, &'static str)]
550#[non_exhaustive]
551pub struct AuthMethodId(pub Arc<str>);
552
553impl AuthMethodId {
554 #[must_use]
556 pub fn new(id: impl Into<Arc<str>>) -> Self {
557 Self(id.into())
558 }
559}
560
561#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
566#[serde(tag = "type", rename_all = "snake_case")]
567#[non_exhaustive]
568pub enum AuthMethod {
569 #[cfg(feature = "unstable_auth_methods")]
575 EnvVar(AuthMethodEnvVar),
576 #[cfg(feature = "unstable_auth_methods")]
582 Terminal(AuthMethodTerminal),
583 #[serde(untagged)]
587 Agent(AuthMethodAgent),
588}
589
590impl AuthMethod {
591 #[must_use]
593 pub fn id(&self) -> &AuthMethodId {
594 match self {
595 Self::Agent(a) => &a.id,
596 #[cfg(feature = "unstable_auth_methods")]
597 Self::EnvVar(e) => &e.id,
598 #[cfg(feature = "unstable_auth_methods")]
599 Self::Terminal(t) => &t.id,
600 }
601 }
602
603 #[must_use]
605 pub fn name(&self) -> &str {
606 match self {
607 Self::Agent(a) => &a.name,
608 #[cfg(feature = "unstable_auth_methods")]
609 Self::EnvVar(e) => &e.name,
610 #[cfg(feature = "unstable_auth_methods")]
611 Self::Terminal(t) => &t.name,
612 }
613 }
614
615 #[must_use]
617 pub fn description(&self) -> Option<&str> {
618 match self {
619 Self::Agent(a) => a.description.as_deref(),
620 #[cfg(feature = "unstable_auth_methods")]
621 Self::EnvVar(e) => e.description.as_deref(),
622 #[cfg(feature = "unstable_auth_methods")]
623 Self::Terminal(t) => t.description.as_deref(),
624 }
625 }
626
627 #[must_use]
633 pub fn meta(&self) -> Option<&Meta> {
634 match self {
635 Self::Agent(a) => a.meta.as_ref(),
636 #[cfg(feature = "unstable_auth_methods")]
637 Self::EnvVar(e) => e.meta.as_ref(),
638 #[cfg(feature = "unstable_auth_methods")]
639 Self::Terminal(t) => t.meta.as_ref(),
640 }
641 }
642}
643
644#[serde_as]
648#[skip_serializing_none]
649#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
650#[serde(rename_all = "camelCase")]
651#[non_exhaustive]
652pub struct AuthMethodAgent {
653 pub id: AuthMethodId,
655 pub name: String,
657 #[serde_as(deserialize_as = "DefaultOnError")]
659 #[schemars(extend("x-deserialize-default-on-error" = true))]
660 #[serde(default)]
661 pub description: Option<String>,
662 #[serde_as(deserialize_as = "DefaultOnError")]
668 #[schemars(extend("x-deserialize-default-on-error" = true))]
669 #[serde(default)]
670 #[serde(rename = "_meta")]
671 pub meta: Option<Meta>,
672}
673
674impl AuthMethodAgent {
675 #[must_use]
677 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
678 Self {
679 id: id.into(),
680 name: name.into(),
681 description: None,
682 meta: None,
683 }
684 }
685
686 #[must_use]
688 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
689 self.description = description.into_option();
690 self
691 }
692
693 #[must_use]
699 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
700 self.meta = meta.into_option();
701 self
702 }
703}
704
705#[cfg(feature = "unstable_auth_methods")]
713#[serde_as]
714#[skip_serializing_none]
715#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
716#[serde(rename_all = "camelCase")]
717#[non_exhaustive]
718pub struct AuthMethodEnvVar {
719 pub id: AuthMethodId,
721 pub name: String,
723 #[serde_as(deserialize_as = "DefaultOnError")]
725 #[schemars(extend("x-deserialize-default-on-error" = true))]
726 #[serde(default)]
727 pub description: Option<String>,
728 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
730 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
731 pub vars: Vec<AuthEnvVar>,
732 #[serde_as(deserialize_as = "DefaultOnError")]
734 #[schemars(extend("x-deserialize-default-on-error" = true))]
735 #[serde(default)]
736 pub link: Option<String>,
737 #[serde_as(deserialize_as = "DefaultOnError")]
743 #[schemars(extend("x-deserialize-default-on-error" = true))]
744 #[serde(default)]
745 #[serde(rename = "_meta")]
746 pub meta: Option<Meta>,
747}
748
749#[cfg(feature = "unstable_auth_methods")]
750impl AuthMethodEnvVar {
751 #[must_use]
753 pub fn new(
754 id: impl Into<AuthMethodId>,
755 name: impl Into<String>,
756 vars: Vec<AuthEnvVar>,
757 ) -> Self {
758 Self {
759 id: id.into(),
760 name: name.into(),
761 description: None,
762 vars,
763 link: None,
764 meta: None,
765 }
766 }
767
768 #[must_use]
770 pub fn link(mut self, link: impl IntoOption<String>) -> Self {
771 self.link = link.into_option();
772 self
773 }
774
775 #[must_use]
777 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
778 self.description = description.into_option();
779 self
780 }
781
782 #[must_use]
788 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
789 self.meta = meta.into_option();
790 self
791 }
792}
793
794#[cfg(feature = "unstable_auth_methods")]
800#[serde_as]
801#[skip_serializing_none]
802#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
803#[serde(rename_all = "camelCase")]
804#[non_exhaustive]
805pub struct AuthEnvVar {
806 pub name: String,
808 #[serde_as(deserialize_as = "DefaultOnError")]
810 #[schemars(extend("x-deserialize-default-on-error" = true))]
811 #[serde(default)]
812 pub label: Option<String>,
813 #[serde_as(deserialize_as = "DefaultTrueOnError")]
818 #[schemars(extend("x-deserialize-default-on-error" = true))]
819 #[serde(default = "default_true", skip_serializing_if = "is_true")]
820 #[schemars(extend("default" = true))]
821 pub secret: bool,
822 #[serde_as(deserialize_as = "DefaultOnError")]
826 #[schemars(extend("x-deserialize-default-on-error" = true))]
827 #[serde(default, skip_serializing_if = "is_false")]
828 #[schemars(extend("default" = false))]
829 pub optional: bool,
830 #[serde_as(deserialize_as = "DefaultOnError")]
836 #[schemars(extend("x-deserialize-default-on-error" = true))]
837 #[serde(default)]
838 #[serde(rename = "_meta")]
839 pub meta: Option<Meta>,
840}
841
842#[cfg(feature = "unstable_auth_methods")]
843fn default_true() -> bool {
844 true
845}
846
847#[cfg(feature = "unstable_auth_methods")]
848#[expect(clippy::trivially_copy_pass_by_ref)]
849fn is_true(v: &bool) -> bool {
850 *v
851}
852
853#[cfg(feature = "unstable_auth_methods")]
854#[expect(clippy::trivially_copy_pass_by_ref)]
855fn is_false(v: &bool) -> bool {
856 !*v
857}
858
859#[cfg(feature = "unstable_auth_methods")]
860impl AuthEnvVar {
861 #[must_use]
863 pub fn new(name: impl Into<String>) -> Self {
864 Self {
865 name: name.into(),
866 label: None,
867 secret: true,
868 optional: false,
869 meta: None,
870 }
871 }
872
873 #[must_use]
875 pub fn label(mut self, label: impl IntoOption<String>) -> Self {
876 self.label = label.into_option();
877 self
878 }
879
880 #[must_use]
883 pub fn secret(mut self, secret: bool) -> Self {
884 self.secret = secret;
885 self
886 }
887
888 #[must_use]
890 pub fn optional(mut self, optional: bool) -> Self {
891 self.optional = optional;
892 self
893 }
894
895 #[must_use]
901 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
902 self.meta = meta.into_option();
903 self
904 }
905}
906
907#[cfg(feature = "unstable_auth_methods")]
915#[serde_as]
916#[skip_serializing_none]
917#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
918#[serde(rename_all = "camelCase")]
919#[non_exhaustive]
920pub struct AuthMethodTerminal {
921 pub id: AuthMethodId,
923 pub name: String,
925 #[serde_as(deserialize_as = "DefaultOnError")]
927 #[schemars(extend("x-deserialize-default-on-error" = true))]
928 #[serde(default)]
929 pub description: Option<String>,
930 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
932 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
933 #[serde(default, skip_serializing_if = "Vec::is_empty")]
934 pub args: Vec<String>,
935 #[serde_as(deserialize_as = "DefaultOnError")]
937 #[schemars(extend("x-deserialize-default-on-error" = true))]
938 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
939 pub env: HashMap<String, String>,
940 #[serde_as(deserialize_as = "DefaultOnError")]
946 #[schemars(extend("x-deserialize-default-on-error" = true))]
947 #[serde(default)]
948 #[serde(rename = "_meta")]
949 pub meta: Option<Meta>,
950}
951
952#[cfg(feature = "unstable_auth_methods")]
953impl AuthMethodTerminal {
954 #[must_use]
956 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
957 Self {
958 id: id.into(),
959 name: name.into(),
960 description: None,
961 args: Vec::new(),
962 env: HashMap::new(),
963 meta: None,
964 }
965 }
966
967 #[must_use]
969 pub fn args(mut self, args: Vec<String>) -> Self {
970 self.args = args;
971 self
972 }
973
974 #[must_use]
976 pub fn env(mut self, env: HashMap<String, String>) -> Self {
977 self.env = env;
978 self
979 }
980
981 #[must_use]
983 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
984 self.description = description.into_option();
985 self
986 }
987
988 #[must_use]
994 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
995 self.meta = meta.into_option();
996 self
997 }
998}
999
1000#[serde_as]
1006#[skip_serializing_none]
1007#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1008#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1009#[serde(rename_all = "camelCase")]
1010#[non_exhaustive]
1011pub struct NewSessionRequest {
1012 pub cwd: PathBuf,
1014 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1020 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1021 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1022 pub additional_directories: Vec<PathBuf>,
1023 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1025 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1026 pub mcp_servers: Vec<McpServer>,
1027 #[serde_as(deserialize_as = "DefaultOnError")]
1033 #[schemars(extend("x-deserialize-default-on-error" = true))]
1034 #[serde(default)]
1035 #[serde(rename = "_meta")]
1036 pub meta: Option<Meta>,
1037}
1038
1039impl NewSessionRequest {
1040 #[must_use]
1042 pub fn new(cwd: impl Into<PathBuf>) -> Self {
1043 Self {
1044 cwd: cwd.into(),
1045 additional_directories: vec![],
1046 mcp_servers: vec![],
1047 meta: None,
1048 }
1049 }
1050
1051 #[must_use]
1053 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1054 self.additional_directories = additional_directories;
1055 self
1056 }
1057
1058 #[must_use]
1060 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1061 self.mcp_servers = mcp_servers;
1062 self
1063 }
1064
1065 #[must_use]
1071 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1072 self.meta = meta.into_option();
1073 self
1074 }
1075}
1076
1077#[serde_as]
1081#[skip_serializing_none]
1082#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1083#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1084#[serde(rename_all = "camelCase")]
1085#[non_exhaustive]
1086pub struct NewSessionResponse {
1087 pub session_id: SessionId,
1091 #[serde_as(deserialize_as = "DefaultOnError")]
1095 #[schemars(extend("x-deserialize-default-on-error" = true))]
1096 #[serde(default)]
1097 pub modes: Option<SessionModeState>,
1098 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1100 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1101 #[serde(default)]
1102 pub config_options: Option<Vec<SessionConfigOption>>,
1103 #[serde_as(deserialize_as = "DefaultOnError")]
1109 #[schemars(extend("x-deserialize-default-on-error" = true))]
1110 #[serde(default)]
1111 #[serde(rename = "_meta")]
1112 pub meta: Option<Meta>,
1113}
1114
1115impl NewSessionResponse {
1116 #[must_use]
1118 pub fn new(session_id: impl Into<SessionId>) -> Self {
1119 Self {
1120 session_id: session_id.into(),
1121 modes: None,
1122 config_options: None,
1123 meta: None,
1124 }
1125 }
1126
1127 #[must_use]
1131 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1132 self.modes = modes.into_option();
1133 self
1134 }
1135
1136 #[must_use]
1138 pub fn config_options(
1139 mut self,
1140 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1141 ) -> Self {
1142 self.config_options = config_options.into_option();
1143 self
1144 }
1145
1146 #[must_use]
1152 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1153 self.meta = meta.into_option();
1154 self
1155 }
1156}
1157
1158#[serde_as]
1166#[skip_serializing_none]
1167#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1168#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1169#[serde(rename_all = "camelCase")]
1170#[non_exhaustive]
1171pub struct LoadSessionRequest {
1172 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1174 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1175 pub mcp_servers: Vec<McpServer>,
1176 pub cwd: PathBuf,
1178 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1185 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1186 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1187 pub additional_directories: Vec<PathBuf>,
1188 pub session_id: SessionId,
1190 #[serde_as(deserialize_as = "DefaultOnError")]
1196 #[schemars(extend("x-deserialize-default-on-error" = true))]
1197 #[serde(default)]
1198 #[serde(rename = "_meta")]
1199 pub meta: Option<Meta>,
1200}
1201
1202impl LoadSessionRequest {
1203 #[must_use]
1205 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1206 Self {
1207 mcp_servers: vec![],
1208 cwd: cwd.into(),
1209 additional_directories: vec![],
1210 session_id: session_id.into(),
1211 meta: None,
1212 }
1213 }
1214
1215 #[must_use]
1217 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1218 self.additional_directories = additional_directories;
1219 self
1220 }
1221
1222 #[must_use]
1224 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1225 self.mcp_servers = mcp_servers;
1226 self
1227 }
1228
1229 #[must_use]
1235 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1236 self.meta = meta.into_option();
1237 self
1238 }
1239}
1240
1241#[serde_as]
1243#[skip_serializing_none]
1244#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1245#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1246#[serde(rename_all = "camelCase")]
1247#[non_exhaustive]
1248pub struct LoadSessionResponse {
1249 #[serde_as(deserialize_as = "DefaultOnError")]
1253 #[schemars(extend("x-deserialize-default-on-error" = true))]
1254 #[serde(default)]
1255 pub modes: Option<SessionModeState>,
1256 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1258 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1259 #[serde(default)]
1260 pub config_options: Option<Vec<SessionConfigOption>>,
1261 #[serde_as(deserialize_as = "DefaultOnError")]
1267 #[schemars(extend("x-deserialize-default-on-error" = true))]
1268 #[serde(default)]
1269 #[serde(rename = "_meta")]
1270 pub meta: Option<Meta>,
1271}
1272
1273impl LoadSessionResponse {
1274 #[must_use]
1276 pub fn new() -> Self {
1277 Self::default()
1278 }
1279
1280 #[must_use]
1284 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1285 self.modes = modes.into_option();
1286 self
1287 }
1288
1289 #[must_use]
1291 pub fn config_options(
1292 mut self,
1293 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1294 ) -> Self {
1295 self.config_options = config_options.into_option();
1296 self
1297 }
1298
1299 #[must_use]
1305 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1306 self.meta = meta.into_option();
1307 self
1308 }
1309}
1310
1311#[cfg(feature = "unstable_session_fork")]
1324#[serde_as]
1325#[skip_serializing_none]
1326#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1327#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1328#[serde(rename_all = "camelCase")]
1329#[non_exhaustive]
1330pub struct ForkSessionRequest {
1331 pub session_id: SessionId,
1333 pub cwd: PathBuf,
1335 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1341 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1342 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1343 pub additional_directories: Vec<PathBuf>,
1344 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1346 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1347 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1348 pub mcp_servers: Vec<McpServer>,
1349 #[serde_as(deserialize_as = "DefaultOnError")]
1355 #[schemars(extend("x-deserialize-default-on-error" = true))]
1356 #[serde(default)]
1357 #[serde(rename = "_meta")]
1358 pub meta: Option<Meta>,
1359}
1360
1361#[cfg(feature = "unstable_session_fork")]
1362impl ForkSessionRequest {
1363 #[must_use]
1365 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1366 Self {
1367 session_id: session_id.into(),
1368 cwd: cwd.into(),
1369 additional_directories: vec![],
1370 mcp_servers: vec![],
1371 meta: None,
1372 }
1373 }
1374
1375 #[must_use]
1377 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1378 self.additional_directories = additional_directories;
1379 self
1380 }
1381
1382 #[must_use]
1384 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1385 self.mcp_servers = mcp_servers;
1386 self
1387 }
1388
1389 #[must_use]
1395 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1396 self.meta = meta.into_option();
1397 self
1398 }
1399}
1400
1401#[cfg(feature = "unstable_session_fork")]
1407#[serde_as]
1408#[skip_serializing_none]
1409#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1410#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1411#[serde(rename_all = "camelCase")]
1412#[non_exhaustive]
1413pub struct ForkSessionResponse {
1414 pub session_id: SessionId,
1416 #[serde_as(deserialize_as = "DefaultOnError")]
1420 #[schemars(extend("x-deserialize-default-on-error" = true))]
1421 #[serde(default)]
1422 pub modes: Option<SessionModeState>,
1423 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1425 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1426 #[serde(default)]
1427 pub config_options: Option<Vec<SessionConfigOption>>,
1428 #[serde_as(deserialize_as = "DefaultOnError")]
1434 #[schemars(extend("x-deserialize-default-on-error" = true))]
1435 #[serde(default)]
1436 #[serde(rename = "_meta")]
1437 pub meta: Option<Meta>,
1438}
1439
1440#[cfg(feature = "unstable_session_fork")]
1441impl ForkSessionResponse {
1442 #[must_use]
1444 pub fn new(session_id: impl Into<SessionId>) -> Self {
1445 Self {
1446 session_id: session_id.into(),
1447 modes: None,
1448 config_options: None,
1449 meta: None,
1450 }
1451 }
1452
1453 #[must_use]
1457 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1458 self.modes = modes.into_option();
1459 self
1460 }
1461
1462 #[must_use]
1464 pub fn config_options(
1465 mut self,
1466 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1467 ) -> Self {
1468 self.config_options = config_options.into_option();
1469 self
1470 }
1471
1472 #[must_use]
1478 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1479 self.meta = meta.into_option();
1480 self
1481 }
1482}
1483
1484#[serde_as]
1493#[skip_serializing_none]
1494#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1495#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1496#[serde(rename_all = "camelCase")]
1497#[non_exhaustive]
1498pub struct ResumeSessionRequest {
1499 pub session_id: SessionId,
1501 pub cwd: PathBuf,
1503 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1510 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1511 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1512 pub additional_directories: Vec<PathBuf>,
1513 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1515 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1516 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1517 pub mcp_servers: Vec<McpServer>,
1518 #[serde_as(deserialize_as = "DefaultOnError")]
1524 #[schemars(extend("x-deserialize-default-on-error" = true))]
1525 #[serde(default)]
1526 #[serde(rename = "_meta")]
1527 pub meta: Option<Meta>,
1528}
1529
1530impl ResumeSessionRequest {
1531 #[must_use]
1533 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1534 Self {
1535 session_id: session_id.into(),
1536 cwd: cwd.into(),
1537 additional_directories: vec![],
1538 mcp_servers: vec![],
1539 meta: None,
1540 }
1541 }
1542
1543 #[must_use]
1545 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1546 self.additional_directories = additional_directories;
1547 self
1548 }
1549
1550 #[must_use]
1552 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1553 self.mcp_servers = mcp_servers;
1554 self
1555 }
1556
1557 #[must_use]
1563 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1564 self.meta = meta.into_option();
1565 self
1566 }
1567}
1568
1569#[serde_as]
1571#[skip_serializing_none]
1572#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1573#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1574#[serde(rename_all = "camelCase")]
1575#[non_exhaustive]
1576pub struct ResumeSessionResponse {
1577 #[serde_as(deserialize_as = "DefaultOnError")]
1581 #[schemars(extend("x-deserialize-default-on-error" = true))]
1582 #[serde(default)]
1583 pub modes: Option<SessionModeState>,
1584 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1586 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1587 #[serde(default)]
1588 pub config_options: Option<Vec<SessionConfigOption>>,
1589 #[serde_as(deserialize_as = "DefaultOnError")]
1595 #[schemars(extend("x-deserialize-default-on-error" = true))]
1596 #[serde(default)]
1597 #[serde(rename = "_meta")]
1598 pub meta: Option<Meta>,
1599}
1600
1601impl ResumeSessionResponse {
1602 #[must_use]
1604 pub fn new() -> Self {
1605 Self::default()
1606 }
1607
1608 #[must_use]
1612 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1613 self.modes = modes.into_option();
1614 self
1615 }
1616
1617 #[must_use]
1619 pub fn config_options(
1620 mut self,
1621 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1622 ) -> Self {
1623 self.config_options = config_options.into_option();
1624 self
1625 }
1626
1627 #[must_use]
1633 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1634 self.meta = meta.into_option();
1635 self
1636 }
1637}
1638
1639#[serde_as]
1649#[skip_serializing_none]
1650#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1651#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1652#[serde(rename_all = "camelCase")]
1653#[non_exhaustive]
1654pub struct CloseSessionRequest {
1655 pub session_id: SessionId,
1657 #[serde_as(deserialize_as = "DefaultOnError")]
1663 #[schemars(extend("x-deserialize-default-on-error" = true))]
1664 #[serde(default)]
1665 #[serde(rename = "_meta")]
1666 pub meta: Option<Meta>,
1667}
1668
1669impl CloseSessionRequest {
1670 #[must_use]
1672 pub fn new(session_id: impl Into<SessionId>) -> Self {
1673 Self {
1674 session_id: session_id.into(),
1675 meta: None,
1676 }
1677 }
1678
1679 #[must_use]
1685 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1686 self.meta = meta.into_option();
1687 self
1688 }
1689}
1690
1691#[serde_as]
1693#[skip_serializing_none]
1694#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1695#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1696#[serde(rename_all = "camelCase")]
1697#[non_exhaustive]
1698pub struct CloseSessionResponse {
1699 #[serde_as(deserialize_as = "DefaultOnError")]
1705 #[schemars(extend("x-deserialize-default-on-error" = true))]
1706 #[serde(default)]
1707 #[serde(rename = "_meta")]
1708 pub meta: Option<Meta>,
1709}
1710
1711impl CloseSessionResponse {
1712 #[must_use]
1714 pub fn new() -> Self {
1715 Self::default()
1716 }
1717
1718 #[must_use]
1724 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1725 self.meta = meta.into_option();
1726 self
1727 }
1728}
1729
1730#[serde_as]
1736#[skip_serializing_none]
1737#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1738#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1739#[serde(rename_all = "camelCase")]
1740#[non_exhaustive]
1741pub struct ListSessionsRequest {
1742 #[serde(default)]
1744 pub cwd: Option<PathBuf>,
1745 #[serde(default)]
1747 pub cursor: Option<String>,
1748 #[serde_as(deserialize_as = "DefaultOnError")]
1754 #[schemars(extend("x-deserialize-default-on-error" = true))]
1755 #[serde(default)]
1756 #[serde(rename = "_meta")]
1757 pub meta: Option<Meta>,
1758}
1759
1760impl ListSessionsRequest {
1761 #[must_use]
1763 pub fn new() -> Self {
1764 Self::default()
1765 }
1766
1767 #[must_use]
1769 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1770 self.cwd = cwd.into_option();
1771 self
1772 }
1773
1774 #[must_use]
1776 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1777 self.cursor = cursor.into_option();
1778 self
1779 }
1780
1781 #[must_use]
1787 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1788 self.meta = meta.into_option();
1789 self
1790 }
1791}
1792
1793#[serde_as]
1795#[skip_serializing_none]
1796#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1797#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1798#[serde(rename_all = "camelCase")]
1799#[non_exhaustive]
1800pub struct ListSessionsResponse {
1801 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1803 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1804 pub sessions: Vec<SessionInfo>,
1805 #[serde_as(deserialize_as = "DefaultOnError")]
1808 #[schemars(extend("x-deserialize-default-on-error" = true))]
1809 #[serde(default)]
1810 pub next_cursor: Option<String>,
1811 #[serde_as(deserialize_as = "DefaultOnError")]
1817 #[schemars(extend("x-deserialize-default-on-error" = true))]
1818 #[serde(default)]
1819 #[serde(rename = "_meta")]
1820 pub meta: Option<Meta>,
1821}
1822
1823impl ListSessionsResponse {
1824 #[must_use]
1826 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1827 Self {
1828 sessions,
1829 next_cursor: None,
1830 meta: None,
1831 }
1832 }
1833
1834 #[must_use]
1836 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1837 self.next_cursor = next_cursor.into_option();
1838 self
1839 }
1840
1841 #[must_use]
1847 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1848 self.meta = meta.into_option();
1849 self
1850 }
1851}
1852
1853#[serde_as]
1859#[skip_serializing_none]
1860#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1861#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1862#[serde(rename_all = "camelCase")]
1863#[non_exhaustive]
1864pub struct DeleteSessionRequest {
1865 pub session_id: SessionId,
1867 #[serde_as(deserialize_as = "DefaultOnError")]
1873 #[schemars(extend("x-deserialize-default-on-error" = true))]
1874 #[serde(default)]
1875 #[serde(rename = "_meta")]
1876 pub meta: Option<Meta>,
1877}
1878
1879impl DeleteSessionRequest {
1880 #[must_use]
1882 pub fn new(session_id: impl Into<SessionId>) -> Self {
1883 Self {
1884 session_id: session_id.into(),
1885 meta: None,
1886 }
1887 }
1888
1889 #[must_use]
1895 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1896 self.meta = meta.into_option();
1897 self
1898 }
1899}
1900
1901#[serde_as]
1903#[skip_serializing_none]
1904#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1905#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1906#[serde(rename_all = "camelCase")]
1907#[non_exhaustive]
1908pub struct DeleteSessionResponse {
1909 #[serde_as(deserialize_as = "DefaultOnError")]
1915 #[schemars(extend("x-deserialize-default-on-error" = true))]
1916 #[serde(default)]
1917 #[serde(rename = "_meta")]
1918 pub meta: Option<Meta>,
1919}
1920
1921impl DeleteSessionResponse {
1922 #[must_use]
1924 pub fn new() -> Self {
1925 Self::default()
1926 }
1927
1928 #[must_use]
1934 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1935 self.meta = meta.into_option();
1936 self
1937 }
1938}
1939
1940#[serde_as]
1942#[skip_serializing_none]
1943#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1944#[serde(rename_all = "camelCase")]
1945#[non_exhaustive]
1946pub struct SessionInfo {
1947 pub session_id: SessionId,
1949 pub cwd: PathBuf,
1951 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1957 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1958 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1959 pub additional_directories: Vec<PathBuf>,
1960
1961 #[serde_as(deserialize_as = "DefaultOnError")]
1963 #[schemars(extend("x-deserialize-default-on-error" = true))]
1964 #[serde(default)]
1965 pub title: Option<String>,
1966 #[serde_as(deserialize_as = "DefaultOnError")]
1968 #[schemars(extend("x-deserialize-default-on-error" = true))]
1969 #[serde(default)]
1970 pub updated_at: Option<String>,
1971 #[serde_as(deserialize_as = "DefaultOnError")]
1977 #[schemars(extend("x-deserialize-default-on-error" = true))]
1978 #[serde(default)]
1979 #[serde(rename = "_meta")]
1980 pub meta: Option<Meta>,
1981}
1982
1983impl SessionInfo {
1984 #[must_use]
1986 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1987 Self {
1988 session_id: session_id.into(),
1989 cwd: cwd.into(),
1990 additional_directories: vec![],
1991 title: None,
1992 updated_at: None,
1993 meta: None,
1994 }
1995 }
1996
1997 #[must_use]
1999 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
2000 self.additional_directories = additional_directories;
2001 self
2002 }
2003
2004 #[must_use]
2006 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
2007 self.title = title.into_option();
2008 self
2009 }
2010
2011 #[must_use]
2013 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
2014 self.updated_at = updated_at.into_option();
2015 self
2016 }
2017
2018 #[must_use]
2024 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2025 self.meta = meta.into_option();
2026 self
2027 }
2028}
2029
2030#[serde_as]
2034#[skip_serializing_none]
2035#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2036#[serde(rename_all = "camelCase")]
2037#[non_exhaustive]
2038pub struct SessionModeState {
2039 pub current_mode_id: SessionModeId,
2041 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2043 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2044 pub available_modes: Vec<SessionMode>,
2045 #[serde_as(deserialize_as = "DefaultOnError")]
2051 #[schemars(extend("x-deserialize-default-on-error" = true))]
2052 #[serde(default)]
2053 #[serde(rename = "_meta")]
2054 pub meta: Option<Meta>,
2055}
2056
2057impl SessionModeState {
2058 #[must_use]
2060 pub fn new(
2061 current_mode_id: impl Into<SessionModeId>,
2062 available_modes: Vec<SessionMode>,
2063 ) -> Self {
2064 Self {
2065 current_mode_id: current_mode_id.into(),
2066 available_modes,
2067 meta: None,
2068 }
2069 }
2070
2071 #[must_use]
2077 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2078 self.meta = meta.into_option();
2079 self
2080 }
2081}
2082
2083#[serde_as]
2087#[skip_serializing_none]
2088#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2089#[serde(rename_all = "camelCase")]
2090#[non_exhaustive]
2091pub struct SessionMode {
2092 pub id: SessionModeId,
2094 pub name: String,
2096 #[serde_as(deserialize_as = "DefaultOnError")]
2098 #[schemars(extend("x-deserialize-default-on-error" = true))]
2099 #[serde(default)]
2100 pub description: Option<String>,
2101 #[serde_as(deserialize_as = "DefaultOnError")]
2107 #[schemars(extend("x-deserialize-default-on-error" = true))]
2108 #[serde(default)]
2109 #[serde(rename = "_meta")]
2110 pub meta: Option<Meta>,
2111}
2112
2113impl SessionMode {
2114 #[must_use]
2116 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
2117 Self {
2118 id: id.into(),
2119 name: name.into(),
2120 description: None,
2121 meta: None,
2122 }
2123 }
2124
2125 #[must_use]
2127 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2128 self.description = description.into_option();
2129 self
2130 }
2131
2132 #[must_use]
2138 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2139 self.meta = meta.into_option();
2140 self
2141 }
2142}
2143
2144#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2146#[serde(transparent)]
2147#[from(Arc<str>, String, &'static str)]
2148#[non_exhaustive]
2149pub struct SessionModeId(pub Arc<str>);
2150
2151impl SessionModeId {
2152 #[must_use]
2154 pub fn new(id: impl Into<Arc<str>>) -> Self {
2155 Self(id.into())
2156 }
2157}
2158
2159#[serde_as]
2161#[skip_serializing_none]
2162#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2163#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2164#[serde(rename_all = "camelCase")]
2165#[non_exhaustive]
2166pub struct SetSessionModeRequest {
2167 pub session_id: SessionId,
2169 pub mode_id: SessionModeId,
2171 #[serde_as(deserialize_as = "DefaultOnError")]
2177 #[schemars(extend("x-deserialize-default-on-error" = true))]
2178 #[serde(default)]
2179 #[serde(rename = "_meta")]
2180 pub meta: Option<Meta>,
2181}
2182
2183impl SetSessionModeRequest {
2184 #[must_use]
2186 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2187 Self {
2188 session_id: session_id.into(),
2189 mode_id: mode_id.into(),
2190 meta: None,
2191 }
2192 }
2193
2194 #[must_use]
2196 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2197 self.meta = meta.into_option();
2198 self
2199 }
2200}
2201
2202#[serde_as]
2204#[skip_serializing_none]
2205#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2206#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2207#[serde(rename_all = "camelCase")]
2208#[non_exhaustive]
2209pub struct SetSessionModeResponse {
2210 #[serde_as(deserialize_as = "DefaultOnError")]
2216 #[schemars(extend("x-deserialize-default-on-error" = true))]
2217 #[serde(default)]
2218 #[serde(rename = "_meta")]
2219 pub meta: Option<Meta>,
2220}
2221
2222impl SetSessionModeResponse {
2223 #[must_use]
2225 pub fn new() -> Self {
2226 Self::default()
2227 }
2228
2229 #[must_use]
2235 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2236 self.meta = meta.into_option();
2237 self
2238 }
2239}
2240
2241#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2245#[serde(transparent)]
2246#[from(Arc<str>, String, &'static str)]
2247#[non_exhaustive]
2248pub struct SessionConfigId(pub Arc<str>);
2249
2250impl SessionConfigId {
2251 #[must_use]
2253 pub fn new(id: impl Into<Arc<str>>) -> Self {
2254 Self(id.into())
2255 }
2256}
2257
2258#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2260#[serde(transparent)]
2261#[from(Arc<str>, String, &'static str)]
2262#[non_exhaustive]
2263pub struct SessionConfigValueId(pub Arc<str>);
2264
2265impl SessionConfigValueId {
2266 #[must_use]
2268 pub fn new(id: impl Into<Arc<str>>) -> Self {
2269 Self(id.into())
2270 }
2271}
2272
2273#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2275#[serde(transparent)]
2276#[from(Arc<str>, String, &'static str)]
2277#[non_exhaustive]
2278pub struct SessionConfigGroupId(pub Arc<str>);
2279
2280impl SessionConfigGroupId {
2281 #[must_use]
2283 pub fn new(id: impl Into<Arc<str>>) -> Self {
2284 Self(id.into())
2285 }
2286}
2287
2288#[serde_as]
2290#[skip_serializing_none]
2291#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2292#[serde(rename_all = "camelCase")]
2293#[non_exhaustive]
2294pub struct SessionConfigSelectOption {
2295 pub value: SessionConfigValueId,
2297 pub name: String,
2299 #[serde_as(deserialize_as = "DefaultOnError")]
2301 #[schemars(extend("x-deserialize-default-on-error" = true))]
2302 #[serde(default)]
2303 pub description: Option<String>,
2304 #[serde_as(deserialize_as = "DefaultOnError")]
2310 #[schemars(extend("x-deserialize-default-on-error" = true))]
2311 #[serde(default)]
2312 #[serde(rename = "_meta")]
2313 pub meta: Option<Meta>,
2314}
2315
2316impl SessionConfigSelectOption {
2317 #[must_use]
2319 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2320 Self {
2321 value: value.into(),
2322 name: name.into(),
2323 description: None,
2324 meta: None,
2325 }
2326 }
2327
2328 #[must_use]
2330 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2331 self.description = description.into_option();
2332 self
2333 }
2334
2335 #[must_use]
2341 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2342 self.meta = meta.into_option();
2343 self
2344 }
2345}
2346
2347#[serde_as]
2349#[skip_serializing_none]
2350#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2351#[serde(rename_all = "camelCase")]
2352#[non_exhaustive]
2353pub struct SessionConfigSelectGroup {
2354 pub group: SessionConfigGroupId,
2356 pub name: String,
2358 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2360 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2361 pub options: Vec<SessionConfigSelectOption>,
2362 #[serde_as(deserialize_as = "DefaultOnError")]
2368 #[schemars(extend("x-deserialize-default-on-error" = true))]
2369 #[serde(default)]
2370 #[serde(rename = "_meta")]
2371 pub meta: Option<Meta>,
2372}
2373
2374impl SessionConfigSelectGroup {
2375 #[must_use]
2377 pub fn new(
2378 group: impl Into<SessionConfigGroupId>,
2379 name: impl Into<String>,
2380 options: Vec<SessionConfigSelectOption>,
2381 ) -> Self {
2382 Self {
2383 group: group.into(),
2384 name: name.into(),
2385 options,
2386 meta: None,
2387 }
2388 }
2389
2390 #[must_use]
2396 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2397 self.meta = meta.into_option();
2398 self
2399 }
2400}
2401
2402#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2404#[serde(untagged)]
2405#[non_exhaustive]
2406pub enum SessionConfigSelectOptions {
2407 Ungrouped(Vec<SessionConfigSelectOption>),
2409 Grouped(Vec<SessionConfigSelectGroup>),
2411}
2412
2413impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2414 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2415 SessionConfigSelectOptions::Ungrouped(options)
2416 }
2417}
2418
2419impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2420 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2421 SessionConfigSelectOptions::Grouped(groups)
2422 }
2423}
2424
2425#[skip_serializing_none]
2427#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2428#[serde(rename_all = "camelCase")]
2429#[non_exhaustive]
2430pub struct SessionConfigSelect {
2431 pub current_value: SessionConfigValueId,
2433 pub options: SessionConfigSelectOptions,
2435}
2436
2437impl SessionConfigSelect {
2438 #[must_use]
2440 pub fn new(
2441 current_value: impl Into<SessionConfigValueId>,
2442 options: impl Into<SessionConfigSelectOptions>,
2443 ) -> Self {
2444 Self {
2445 current_value: current_value.into(),
2446 options: options.into(),
2447 }
2448 }
2449}
2450
2451#[skip_serializing_none]
2453#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2454#[serde(rename_all = "camelCase")]
2455#[non_exhaustive]
2456pub struct SessionConfigBoolean {
2457 pub current_value: bool,
2459}
2460
2461impl SessionConfigBoolean {
2462 #[must_use]
2464 pub fn new(current_value: bool) -> Self {
2465 Self { current_value }
2466 }
2467}
2468
2469#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2479#[serde(rename_all = "snake_case")]
2480#[non_exhaustive]
2481pub enum SessionConfigOptionCategory {
2482 Mode,
2484 Model,
2486 ModelConfig,
2488 ThoughtLevel,
2490 #[serde(untagged)]
2492 Other(String),
2493}
2494
2495#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2497#[serde(tag = "type", rename_all = "snake_case")]
2498#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2499#[non_exhaustive]
2500pub enum SessionConfigKind {
2501 Select(SessionConfigSelect),
2503 Boolean(SessionConfigBoolean),
2505}
2506
2507#[serde_as]
2509#[skip_serializing_none]
2510#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2511#[serde(rename_all = "camelCase")]
2512#[non_exhaustive]
2513pub struct SessionConfigOption {
2514 pub id: SessionConfigId,
2516 pub name: String,
2518 #[serde_as(deserialize_as = "DefaultOnError")]
2520 #[schemars(extend("x-deserialize-default-on-error" = true))]
2521 #[serde(default)]
2522 pub description: Option<String>,
2523 #[serde_as(deserialize_as = "DefaultOnError")]
2525 #[schemars(extend("x-deserialize-default-on-error" = true))]
2526 #[serde(default)]
2527 pub category: Option<SessionConfigOptionCategory>,
2528 #[serde(flatten)]
2530 pub kind: SessionConfigKind,
2531 #[serde_as(deserialize_as = "DefaultOnError")]
2537 #[schemars(extend("x-deserialize-default-on-error" = true))]
2538 #[serde(default)]
2539 #[serde(rename = "_meta")]
2540 pub meta: Option<Meta>,
2541}
2542
2543impl SessionConfigOption {
2544 #[must_use]
2546 pub fn new(
2547 id: impl Into<SessionConfigId>,
2548 name: impl Into<String>,
2549 kind: SessionConfigKind,
2550 ) -> Self {
2551 Self {
2552 id: id.into(),
2553 name: name.into(),
2554 description: None,
2555 category: None,
2556 kind,
2557 meta: None,
2558 }
2559 }
2560
2561 #[must_use]
2563 pub fn select(
2564 id: impl Into<SessionConfigId>,
2565 name: impl Into<String>,
2566 current_value: impl Into<SessionConfigValueId>,
2567 options: impl Into<SessionConfigSelectOptions>,
2568 ) -> Self {
2569 Self::new(
2570 id,
2571 name,
2572 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2573 )
2574 }
2575
2576 #[must_use]
2578 pub fn boolean(
2579 id: impl Into<SessionConfigId>,
2580 name: impl Into<String>,
2581 current_value: bool,
2582 ) -> Self {
2583 Self::new(
2584 id,
2585 name,
2586 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2587 )
2588 }
2589
2590 #[must_use]
2592 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2593 self.description = description.into_option();
2594 self
2595 }
2596
2597 #[must_use]
2599 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2600 self.category = category.into_option();
2601 self
2602 }
2603
2604 #[must_use]
2610 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2611 self.meta = meta.into_option();
2612 self
2613 }
2614}
2615
2616#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2627#[serde(tag = "type", rename_all = "snake_case")]
2628#[non_exhaustive]
2629pub enum SessionConfigOptionValue {
2630 Boolean {
2632 value: bool,
2634 },
2635 #[serde(untagged)]
2641 ValueId {
2642 value: SessionConfigValueId,
2644 },
2645}
2646
2647impl SessionConfigOptionValue {
2648 #[must_use]
2650 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2651 Self::ValueId { value: id.into() }
2652 }
2653
2654 #[must_use]
2656 pub fn boolean(val: bool) -> Self {
2657 Self::Boolean { value: val }
2658 }
2659
2660 #[must_use]
2663 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2664 match self {
2665 Self::ValueId { value } => Some(value),
2666 _ => None,
2667 }
2668 }
2669
2670 #[must_use]
2672 pub fn as_bool(&self) -> Option<bool> {
2673 match self {
2674 Self::Boolean { value } => Some(*value),
2675 _ => None,
2676 }
2677 }
2678}
2679
2680impl From<SessionConfigValueId> for SessionConfigOptionValue {
2681 fn from(value: SessionConfigValueId) -> Self {
2682 Self::ValueId { value }
2683 }
2684}
2685
2686impl From<bool> for SessionConfigOptionValue {
2687 fn from(value: bool) -> Self {
2688 Self::Boolean { value }
2689 }
2690}
2691
2692impl From<&str> for SessionConfigOptionValue {
2693 fn from(value: &str) -> Self {
2694 Self::ValueId {
2695 value: SessionConfigValueId::new(value),
2696 }
2697 }
2698}
2699
2700#[serde_as]
2702#[skip_serializing_none]
2703#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2704#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2705#[serde(rename_all = "camelCase")]
2706#[non_exhaustive]
2707pub struct SetSessionConfigOptionRequest {
2708 pub session_id: SessionId,
2710 pub config_id: SessionConfigId,
2712 #[serde(flatten)]
2717 pub value: SessionConfigOptionValue,
2718 #[serde_as(deserialize_as = "DefaultOnError")]
2724 #[schemars(extend("x-deserialize-default-on-error" = true))]
2725 #[serde(default)]
2726 #[serde(rename = "_meta")]
2727 pub meta: Option<Meta>,
2728}
2729
2730impl SetSessionConfigOptionRequest {
2731 #[must_use]
2733 pub fn new(
2734 session_id: impl Into<SessionId>,
2735 config_id: impl Into<SessionConfigId>,
2736 value: impl Into<SessionConfigOptionValue>,
2737 ) -> Self {
2738 Self {
2739 session_id: session_id.into(),
2740 config_id: config_id.into(),
2741 value: value.into(),
2742 meta: None,
2743 }
2744 }
2745
2746 #[must_use]
2752 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2753 self.meta = meta.into_option();
2754 self
2755 }
2756}
2757
2758#[serde_as]
2760#[skip_serializing_none]
2761#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2762#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2763#[serde(rename_all = "camelCase")]
2764#[non_exhaustive]
2765pub struct SetSessionConfigOptionResponse {
2766 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2768 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2769 pub config_options: Vec<SessionConfigOption>,
2770 #[serde_as(deserialize_as = "DefaultOnError")]
2776 #[schemars(extend("x-deserialize-default-on-error" = true))]
2777 #[serde(default)]
2778 #[serde(rename = "_meta")]
2779 pub meta: Option<Meta>,
2780}
2781
2782impl SetSessionConfigOptionResponse {
2783 #[must_use]
2785 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2786 Self {
2787 config_options,
2788 meta: None,
2789 }
2790 }
2791
2792 #[must_use]
2798 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2799 self.meta = meta.into_option();
2800 self
2801 }
2802}
2803
2804#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2813#[serde(tag = "type", rename_all = "snake_case")]
2814#[non_exhaustive]
2815pub enum McpServer {
2816 Http(McpServerHttp),
2820 Sse(McpServerSse),
2824 #[cfg(feature = "unstable_mcp_over_acp")]
2833 Acp(McpServerAcp),
2834 #[serde(untagged)]
2838 Stdio(McpServerStdio),
2839}
2840
2841#[serde_as]
2843#[skip_serializing_none]
2844#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2845#[serde(rename_all = "camelCase")]
2846#[non_exhaustive]
2847pub struct McpServerHttp {
2848 pub name: String,
2850 pub url: String,
2852 pub headers: Vec<HttpHeader>,
2854 #[serde_as(deserialize_as = "DefaultOnError")]
2860 #[schemars(extend("x-deserialize-default-on-error" = true))]
2861 #[serde(default)]
2862 #[serde(rename = "_meta")]
2863 pub meta: Option<Meta>,
2864}
2865
2866impl McpServerHttp {
2867 #[must_use]
2869 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2870 Self {
2871 name: name.into(),
2872 url: url.into(),
2873 headers: Vec::new(),
2874 meta: None,
2875 }
2876 }
2877
2878 #[must_use]
2880 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2881 self.headers = headers;
2882 self
2883 }
2884
2885 #[must_use]
2891 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2892 self.meta = meta.into_option();
2893 self
2894 }
2895}
2896
2897#[serde_as]
2899#[skip_serializing_none]
2900#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2901#[serde(rename_all = "camelCase")]
2902#[non_exhaustive]
2903pub struct McpServerSse {
2904 pub name: String,
2906 pub url: String,
2908 pub headers: Vec<HttpHeader>,
2910 #[serde_as(deserialize_as = "DefaultOnError")]
2916 #[schemars(extend("x-deserialize-default-on-error" = true))]
2917 #[serde(default)]
2918 #[serde(rename = "_meta")]
2919 pub meta: Option<Meta>,
2920}
2921
2922impl McpServerSse {
2923 #[must_use]
2925 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2926 Self {
2927 name: name.into(),
2928 url: url.into(),
2929 headers: Vec::new(),
2930 meta: None,
2931 }
2932 }
2933
2934 #[must_use]
2936 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2937 self.headers = headers;
2938 self
2939 }
2940
2941 #[must_use]
2947 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2948 self.meta = meta.into_option();
2949 self
2950 }
2951}
2952
2953#[cfg(feature = "unstable_mcp_over_acp")]
2963#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2964#[serde(transparent)]
2965#[from(Arc<str>, String, &'static str)]
2966#[non_exhaustive]
2967pub struct McpServerAcpId(pub Arc<str>);
2968
2969#[cfg(feature = "unstable_mcp_over_acp")]
2970impl McpServerAcpId {
2971 #[must_use]
2973 pub fn new(id: impl Into<Arc<str>>) -> Self {
2974 Self(id.into())
2975 }
2976}
2977
2978#[serde_as]
2987#[skip_serializing_none]
2988#[cfg(feature = "unstable_mcp_over_acp")]
2989#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2990#[serde(rename_all = "camelCase")]
2991#[non_exhaustive]
2992pub struct McpServerAcp {
2993 pub name: String,
2995 pub server_id: McpServerAcpId,
3000 #[serde_as(deserialize_as = "DefaultOnError")]
3006 #[schemars(extend("x-deserialize-default-on-error" = true))]
3007 #[serde(default)]
3008 #[serde(rename = "_meta")]
3009 pub meta: Option<Meta>,
3010}
3011
3012#[cfg(feature = "unstable_mcp_over_acp")]
3013impl McpServerAcp {
3014 #[must_use]
3016 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
3017 Self {
3018 name: name.into(),
3019 server_id: id.into(),
3020 meta: None,
3021 }
3022 }
3023
3024 #[must_use]
3030 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3031 self.meta = meta.into_option();
3032 self
3033 }
3034}
3035
3036#[serde_as]
3038#[skip_serializing_none]
3039#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3040#[serde(rename_all = "camelCase")]
3041#[non_exhaustive]
3042pub struct McpServerStdio {
3043 pub name: String,
3045 pub command: PathBuf,
3047 pub args: Vec<String>,
3049 pub env: Vec<EnvVariable>,
3051 #[serde_as(deserialize_as = "DefaultOnError")]
3057 #[schemars(extend("x-deserialize-default-on-error" = true))]
3058 #[serde(default)]
3059 #[serde(rename = "_meta")]
3060 pub meta: Option<Meta>,
3061}
3062
3063impl McpServerStdio {
3064 #[must_use]
3066 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
3067 Self {
3068 name: name.into(),
3069 command: command.into(),
3070 args: Vec::new(),
3071 env: Vec::new(),
3072 meta: None,
3073 }
3074 }
3075
3076 #[must_use]
3078 pub fn args(mut self, args: Vec<String>) -> Self {
3079 self.args = args;
3080 self
3081 }
3082
3083 #[must_use]
3085 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
3086 self.env = env;
3087 self
3088 }
3089
3090 #[must_use]
3096 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3097 self.meta = meta.into_option();
3098 self
3099 }
3100}
3101
3102#[serde_as]
3104#[skip_serializing_none]
3105#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3106#[serde(rename_all = "camelCase")]
3107#[non_exhaustive]
3108pub struct EnvVariable {
3109 pub name: String,
3111 pub value: String,
3113 #[serde_as(deserialize_as = "DefaultOnError")]
3119 #[schemars(extend("x-deserialize-default-on-error" = true))]
3120 #[serde(default)]
3121 #[serde(rename = "_meta")]
3122 pub meta: Option<Meta>,
3123}
3124
3125impl EnvVariable {
3126 #[must_use]
3128 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3129 Self {
3130 name: name.into(),
3131 value: value.into(),
3132 meta: None,
3133 }
3134 }
3135
3136 #[must_use]
3142 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3143 self.meta = meta.into_option();
3144 self
3145 }
3146}
3147
3148#[serde_as]
3150#[skip_serializing_none]
3151#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3152#[serde(rename_all = "camelCase")]
3153#[non_exhaustive]
3154pub struct HttpHeader {
3155 pub name: String,
3157 pub value: String,
3159 #[serde_as(deserialize_as = "DefaultOnError")]
3165 #[schemars(extend("x-deserialize-default-on-error" = true))]
3166 #[serde(default)]
3167 #[serde(rename = "_meta")]
3168 pub meta: Option<Meta>,
3169}
3170
3171impl HttpHeader {
3172 #[must_use]
3174 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3175 Self {
3176 name: name.into(),
3177 value: value.into(),
3178 meta: None,
3179 }
3180 }
3181
3182 #[must_use]
3188 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3189 self.meta = meta.into_option();
3190 self
3191 }
3192}
3193
3194#[serde_as]
3202#[skip_serializing_none]
3203#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3204#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3205#[serde(rename_all = "camelCase")]
3206#[non_exhaustive]
3207pub struct PromptRequest {
3208 pub session_id: SessionId,
3210 pub prompt: Vec<ContentBlock>,
3224 #[serde_as(deserialize_as = "DefaultOnError")]
3230 #[schemars(extend("x-deserialize-default-on-error" = true))]
3231 #[serde(default)]
3232 #[serde(rename = "_meta")]
3233 pub meta: Option<Meta>,
3234}
3235
3236impl PromptRequest {
3237 #[must_use]
3239 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3240 Self {
3241 session_id: session_id.into(),
3242 prompt,
3243 meta: None,
3244 }
3245 }
3246
3247 #[must_use]
3253 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3254 self.meta = meta.into_option();
3255 self
3256 }
3257}
3258
3259#[serde_as]
3263#[skip_serializing_none]
3264#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3265#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3266#[serde(rename_all = "camelCase")]
3267#[non_exhaustive]
3268pub struct PromptResponse {
3269 pub stop_reason: StopReason,
3271 #[cfg(feature = "unstable_end_turn_token_usage")]
3277 #[serde_as(deserialize_as = "DefaultOnError")]
3278 #[schemars(extend("x-deserialize-default-on-error" = true))]
3279 #[serde(default)]
3280 pub usage: Option<Usage>,
3281 #[serde_as(deserialize_as = "DefaultOnError")]
3287 #[schemars(extend("x-deserialize-default-on-error" = true))]
3288 #[serde(default)]
3289 #[serde(rename = "_meta")]
3290 pub meta: Option<Meta>,
3291}
3292
3293impl PromptResponse {
3294 #[must_use]
3296 pub fn new(stop_reason: StopReason) -> Self {
3297 Self {
3298 stop_reason,
3299 #[cfg(feature = "unstable_end_turn_token_usage")]
3300 usage: None,
3301 meta: None,
3302 }
3303 }
3304
3305 #[cfg(feature = "unstable_end_turn_token_usage")]
3311 #[must_use]
3312 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3313 self.usage = usage.into_option();
3314 self
3315 }
3316
3317 #[must_use]
3323 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3324 self.meta = meta.into_option();
3325 self
3326 }
3327}
3328
3329#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3333#[serde(rename_all = "snake_case")]
3334#[non_exhaustive]
3335pub enum StopReason {
3336 EndTurn,
3338 MaxTokens,
3340 MaxTurnRequests,
3343 Refusal,
3347 Cancelled,
3354}
3355
3356#[cfg(feature = "unstable_end_turn_token_usage")]
3362#[serde_as]
3363#[skip_serializing_none]
3364#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3365#[serde(rename_all = "camelCase")]
3366#[non_exhaustive]
3367pub struct Usage {
3368 pub total_tokens: u64,
3370 pub input_tokens: u64,
3372 pub output_tokens: u64,
3374 #[serde_as(deserialize_as = "DefaultOnError")]
3376 #[schemars(extend("x-deserialize-default-on-error" = true))]
3377 #[serde(default)]
3378 pub thought_tokens: Option<u64>,
3379 #[serde_as(deserialize_as = "DefaultOnError")]
3381 #[schemars(extend("x-deserialize-default-on-error" = true))]
3382 #[serde(default)]
3383 pub cached_read_tokens: Option<u64>,
3384 #[serde_as(deserialize_as = "DefaultOnError")]
3386 #[schemars(extend("x-deserialize-default-on-error" = true))]
3387 #[serde(default)]
3388 pub cached_write_tokens: Option<u64>,
3389 #[serde_as(deserialize_as = "DefaultOnError")]
3395 #[schemars(extend("x-deserialize-default-on-error" = true))]
3396 #[serde(default)]
3397 #[serde(rename = "_meta")]
3398 pub meta: Option<Meta>,
3399}
3400
3401#[cfg(feature = "unstable_end_turn_token_usage")]
3402impl Usage {
3403 #[must_use]
3405 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3406 Self {
3407 total_tokens,
3408 input_tokens,
3409 output_tokens,
3410 thought_tokens: None,
3411 cached_read_tokens: None,
3412 cached_write_tokens: None,
3413 meta: None,
3414 }
3415 }
3416
3417 #[must_use]
3419 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3420 self.thought_tokens = thought_tokens.into_option();
3421 self
3422 }
3423
3424 #[must_use]
3426 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3427 self.cached_read_tokens = cached_read_tokens.into_option();
3428 self
3429 }
3430
3431 #[must_use]
3433 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3434 self.cached_write_tokens = cached_write_tokens.into_option();
3435 self
3436 }
3437
3438 #[must_use]
3444 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3445 self.meta = meta.into_option();
3446 self
3447 }
3448}
3449
3450#[cfg(feature = "unstable_llm_providers")]
3463#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3464#[serde(rename_all = "snake_case")]
3465#[non_exhaustive]
3466#[expect(clippy::doc_markdown)]
3467pub enum LlmProtocol {
3468 Anthropic,
3470 #[serde(rename = "openai")]
3472 OpenAi,
3473 Azure,
3475 Vertex,
3477 Bedrock,
3479 #[serde(untagged)]
3481 Other(String),
3482}
3483
3484#[cfg(feature = "unstable_llm_providers")]
3490#[serde_as]
3491#[skip_serializing_none]
3492#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3493#[serde(rename_all = "camelCase")]
3494#[non_exhaustive]
3495pub struct ProviderCurrentConfig {
3496 pub api_type: LlmProtocol,
3498 pub base_url: String,
3500 #[serde_as(deserialize_as = "DefaultOnError")]
3506 #[schemars(extend("x-deserialize-default-on-error" = true))]
3507 #[serde(default)]
3508 #[serde(rename = "_meta")]
3509 pub meta: Option<Meta>,
3510}
3511
3512#[cfg(feature = "unstable_llm_providers")]
3513impl ProviderCurrentConfig {
3514 #[must_use]
3516 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3517 Self {
3518 api_type,
3519 base_url: base_url.into(),
3520 meta: None,
3521 }
3522 }
3523
3524 #[must_use]
3530 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3531 self.meta = meta.into_option();
3532 self
3533 }
3534}
3535
3536#[cfg(feature = "unstable_llm_providers")]
3542#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
3543#[serde(transparent)]
3544#[from(Arc<str>, String, &'static str)]
3545#[non_exhaustive]
3546pub struct ProviderId(pub Arc<str>);
3547
3548#[cfg(feature = "unstable_llm_providers")]
3549impl ProviderId {
3550 #[must_use]
3552 pub fn new(id: impl Into<Arc<str>>) -> Self {
3553 Self(id.into())
3554 }
3555}
3556
3557#[cfg(feature = "unstable_llm_providers")]
3563#[serde_as]
3564#[skip_serializing_none]
3565#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3566#[serde(rename_all = "camelCase")]
3567#[non_exhaustive]
3568pub struct ProviderInfo {
3569 pub provider_id: ProviderId,
3571 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3573 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3574 pub supported: Vec<LlmProtocol>,
3575 pub required: bool,
3578 #[serde(default)]
3581 pub current: Option<ProviderCurrentConfig>,
3582 #[serde_as(deserialize_as = "DefaultOnError")]
3588 #[schemars(extend("x-deserialize-default-on-error" = true))]
3589 #[serde(default)]
3590 #[serde(rename = "_meta")]
3591 pub meta: Option<Meta>,
3592}
3593
3594#[cfg(feature = "unstable_llm_providers")]
3595impl ProviderInfo {
3596 #[must_use]
3598 pub fn new(
3599 provider_id: impl Into<ProviderId>,
3600 supported: Vec<LlmProtocol>,
3601 required: bool,
3602 current: impl IntoOption<ProviderCurrentConfig>,
3603 ) -> Self {
3604 Self {
3605 provider_id: provider_id.into(),
3606 supported,
3607 required,
3608 current: current.into_option(),
3609 meta: None,
3610 }
3611 }
3612
3613 #[must_use]
3619 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3620 self.meta = meta.into_option();
3621 self
3622 }
3623}
3624
3625#[cfg(feature = "unstable_llm_providers")]
3631#[serde_as]
3632#[skip_serializing_none]
3633#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3634#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3635#[serde(rename_all = "camelCase")]
3636#[non_exhaustive]
3637pub struct ListProvidersRequest {
3638 #[serde_as(deserialize_as = "DefaultOnError")]
3644 #[schemars(extend("x-deserialize-default-on-error" = true))]
3645 #[serde(default)]
3646 #[serde(rename = "_meta")]
3647 pub meta: Option<Meta>,
3648}
3649
3650#[cfg(feature = "unstable_llm_providers")]
3651impl ListProvidersRequest {
3652 #[must_use]
3654 pub fn new() -> Self {
3655 Self::default()
3656 }
3657
3658 #[must_use]
3664 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3665 self.meta = meta.into_option();
3666 self
3667 }
3668}
3669
3670#[cfg(feature = "unstable_llm_providers")]
3676#[serde_as]
3677#[skip_serializing_none]
3678#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3679#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3680#[serde(rename_all = "camelCase")]
3681#[non_exhaustive]
3682pub struct ListProvidersResponse {
3683 pub providers: Vec<ProviderInfo>,
3685 #[serde_as(deserialize_as = "DefaultOnError")]
3691 #[schemars(extend("x-deserialize-default-on-error" = true))]
3692 #[serde(default)]
3693 #[serde(rename = "_meta")]
3694 pub meta: Option<Meta>,
3695}
3696
3697#[cfg(feature = "unstable_llm_providers")]
3698impl ListProvidersResponse {
3699 #[must_use]
3701 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3702 Self {
3703 providers,
3704 meta: None,
3705 }
3706 }
3707
3708 #[must_use]
3714 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3715 self.meta = meta.into_option();
3716 self
3717 }
3718}
3719
3720#[cfg(feature = "unstable_llm_providers")]
3728#[serde_as]
3729#[skip_serializing_none]
3730#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3731#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3732#[serde(rename_all = "camelCase")]
3733#[non_exhaustive]
3734pub struct SetProviderRequest {
3735 pub provider_id: ProviderId,
3737 pub api_type: LlmProtocol,
3739 pub base_url: String,
3741 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3744 pub headers: HashMap<String, String>,
3745 #[serde_as(deserialize_as = "DefaultOnError")]
3751 #[schemars(extend("x-deserialize-default-on-error" = true))]
3752 #[serde(default)]
3753 #[serde(rename = "_meta")]
3754 pub meta: Option<Meta>,
3755}
3756
3757#[cfg(feature = "unstable_llm_providers")]
3758impl SetProviderRequest {
3759 #[must_use]
3761 pub fn new(
3762 provider_id: impl Into<ProviderId>,
3763 api_type: LlmProtocol,
3764 base_url: impl Into<String>,
3765 ) -> Self {
3766 Self {
3767 provider_id: provider_id.into(),
3768 api_type,
3769 base_url: base_url.into(),
3770 headers: HashMap::new(),
3771 meta: None,
3772 }
3773 }
3774
3775 #[must_use]
3778 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3779 self.headers = headers;
3780 self
3781 }
3782
3783 #[must_use]
3789 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3790 self.meta = meta.into_option();
3791 self
3792 }
3793}
3794
3795#[cfg(feature = "unstable_llm_providers")]
3801#[serde_as]
3802#[skip_serializing_none]
3803#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3804#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3805#[serde(rename_all = "camelCase")]
3806#[non_exhaustive]
3807pub struct SetProviderResponse {
3808 #[serde_as(deserialize_as = "DefaultOnError")]
3814 #[schemars(extend("x-deserialize-default-on-error" = true))]
3815 #[serde(default)]
3816 #[serde(rename = "_meta")]
3817 pub meta: Option<Meta>,
3818}
3819
3820#[cfg(feature = "unstable_llm_providers")]
3821impl SetProviderResponse {
3822 #[must_use]
3824 pub fn new() -> Self {
3825 Self::default()
3826 }
3827
3828 #[must_use]
3834 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3835 self.meta = meta.into_option();
3836 self
3837 }
3838}
3839
3840#[cfg(feature = "unstable_llm_providers")]
3846#[serde_as]
3847#[skip_serializing_none]
3848#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3849#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3850#[serde(rename_all = "camelCase")]
3851#[non_exhaustive]
3852pub struct DisableProviderRequest {
3853 pub provider_id: ProviderId,
3855 #[serde_as(deserialize_as = "DefaultOnError")]
3861 #[schemars(extend("x-deserialize-default-on-error" = true))]
3862 #[serde(default)]
3863 #[serde(rename = "_meta")]
3864 pub meta: Option<Meta>,
3865}
3866
3867#[cfg(feature = "unstable_llm_providers")]
3868impl DisableProviderRequest {
3869 #[must_use]
3871 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
3872 Self {
3873 provider_id: provider_id.into(),
3874 meta: None,
3875 }
3876 }
3877
3878 #[must_use]
3884 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3885 self.meta = meta.into_option();
3886 self
3887 }
3888}
3889
3890#[cfg(feature = "unstable_llm_providers")]
3896#[serde_as]
3897#[skip_serializing_none]
3898#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3899#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3900#[serde(rename_all = "camelCase")]
3901#[non_exhaustive]
3902pub struct DisableProviderResponse {
3903 #[serde_as(deserialize_as = "DefaultOnError")]
3909 #[schemars(extend("x-deserialize-default-on-error" = true))]
3910 #[serde(default)]
3911 #[serde(rename = "_meta")]
3912 pub meta: Option<Meta>,
3913}
3914
3915#[cfg(feature = "unstable_llm_providers")]
3916impl DisableProviderResponse {
3917 #[must_use]
3919 pub fn new() -> Self {
3920 Self::default()
3921 }
3922
3923 #[must_use]
3929 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3930 self.meta = meta.into_option();
3931 self
3932 }
3933}
3934
3935#[serde_as]
3944#[skip_serializing_none]
3945#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3946#[serde(rename_all = "camelCase")]
3947#[non_exhaustive]
3948pub struct AgentCapabilities {
3949 #[serde_as(deserialize_as = "DefaultOnError")]
3951 #[schemars(extend("x-deserialize-default-on-error" = true))]
3952 #[serde(default)]
3953 pub load_session: bool,
3954 #[serde_as(deserialize_as = "DefaultOnError")]
3956 #[schemars(extend("x-deserialize-default-on-error" = true))]
3957 #[serde(default)]
3958 pub prompt_capabilities: PromptCapabilities,
3959 #[serde_as(deserialize_as = "DefaultOnError")]
3961 #[schemars(extend("x-deserialize-default-on-error" = true))]
3962 #[serde(default)]
3963 pub mcp_capabilities: McpCapabilities,
3964 #[serde_as(deserialize_as = "DefaultOnError")]
3966 #[schemars(extend("x-deserialize-default-on-error" = true))]
3967 #[serde(default)]
3968 pub session_capabilities: SessionCapabilities,
3969 #[serde_as(deserialize_as = "DefaultOnError")]
3971 #[schemars(extend("x-deserialize-default-on-error" = true))]
3972 #[serde(default)]
3973 pub auth: AgentAuthCapabilities,
3974 #[cfg(feature = "unstable_llm_providers")]
3983 #[serde_as(deserialize_as = "DefaultOnError")]
3984 #[schemars(extend("x-deserialize-default-on-error" = true))]
3985 #[serde(default)]
3986 pub providers: Option<ProvidersCapabilities>,
3987 #[cfg(feature = "unstable_nes")]
3996 #[serde_as(deserialize_as = "DefaultOnError")]
3997 #[schemars(extend("x-deserialize-default-on-error" = true))]
3998 #[serde(default)]
3999 pub nes: Option<NesCapabilities>,
4000 #[cfg(feature = "unstable_nes")]
4006 #[serde_as(deserialize_as = "DefaultOnError")]
4007 #[schemars(extend("x-deserialize-default-on-error" = true))]
4008 #[serde(default)]
4009 pub position_encoding: Option<PositionEncodingKind>,
4010 #[serde_as(deserialize_as = "DefaultOnError")]
4016 #[schemars(extend("x-deserialize-default-on-error" = true))]
4017 #[serde(default)]
4018 #[serde(rename = "_meta")]
4019 pub meta: Option<Meta>,
4020}
4021
4022impl AgentCapabilities {
4023 #[must_use]
4025 pub fn new() -> Self {
4026 Self::default()
4027 }
4028
4029 #[must_use]
4031 pub fn load_session(mut self, load_session: bool) -> Self {
4032 self.load_session = load_session;
4033 self
4034 }
4035
4036 #[must_use]
4038 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
4039 self.prompt_capabilities = prompt_capabilities;
4040 self
4041 }
4042
4043 #[must_use]
4045 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
4046 self.mcp_capabilities = mcp_capabilities;
4047 self
4048 }
4049
4050 #[must_use]
4052 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
4053 self.session_capabilities = session_capabilities;
4054 self
4055 }
4056
4057 #[must_use]
4059 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
4060 self.auth = auth;
4061 self
4062 }
4063
4064 #[cfg(feature = "unstable_llm_providers")]
4070 #[must_use]
4071 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
4072 self.providers = providers.into_option();
4073 self
4074 }
4075
4076 #[cfg(feature = "unstable_nes")]
4082 #[must_use]
4083 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
4084 self.nes = nes.into_option();
4085 self
4086 }
4087
4088 #[cfg(feature = "unstable_nes")]
4092 #[must_use]
4093 pub fn position_encoding(
4094 mut self,
4095 position_encoding: impl IntoOption<PositionEncodingKind>,
4096 ) -> Self {
4097 self.position_encoding = position_encoding.into_option();
4098 self
4099 }
4100
4101 #[must_use]
4107 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4108 self.meta = meta.into_option();
4109 self
4110 }
4111}
4112
4113#[cfg(feature = "unstable_llm_providers")]
4121#[serde_as]
4122#[skip_serializing_none]
4123#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4124#[non_exhaustive]
4125pub struct ProvidersCapabilities {
4126 #[serde_as(deserialize_as = "DefaultOnError")]
4132 #[schemars(extend("x-deserialize-default-on-error" = true))]
4133 #[serde(default)]
4134 #[serde(rename = "_meta")]
4135 pub meta: Option<Meta>,
4136}
4137
4138#[cfg(feature = "unstable_llm_providers")]
4139impl ProvidersCapabilities {
4140 #[must_use]
4142 pub fn new() -> Self {
4143 Self::default()
4144 }
4145
4146 #[must_use]
4152 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4153 self.meta = meta.into_option();
4154 self
4155 }
4156}
4157
4158#[serde_as]
4168#[skip_serializing_none]
4169#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4170#[serde(rename_all = "camelCase")]
4171#[non_exhaustive]
4172pub struct SessionCapabilities {
4173 #[serde_as(deserialize_as = "DefaultOnError")]
4178 #[schemars(extend("x-deserialize-default-on-error" = true))]
4179 #[serde(default)]
4180 pub list: Option<SessionListCapabilities>,
4181 #[serde_as(deserialize_as = "DefaultOnError")]
4186 #[schemars(extend("x-deserialize-default-on-error" = true))]
4187 #[serde(default)]
4188 pub delete: Option<SessionDeleteCapabilities>,
4189 #[serde_as(deserialize_as = "DefaultOnError")]
4199 #[schemars(extend("x-deserialize-default-on-error" = true))]
4200 #[serde(default)]
4201 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4202 #[cfg(feature = "unstable_session_fork")]
4211 #[serde_as(deserialize_as = "DefaultOnError")]
4212 #[schemars(extend("x-deserialize-default-on-error" = true))]
4213 #[serde(default)]
4214 pub fork: Option<SessionForkCapabilities>,
4215 #[serde_as(deserialize_as = "DefaultOnError")]
4220 #[schemars(extend("x-deserialize-default-on-error" = true))]
4221 #[serde(default)]
4222 pub resume: Option<SessionResumeCapabilities>,
4223 #[serde_as(deserialize_as = "DefaultOnError")]
4228 #[schemars(extend("x-deserialize-default-on-error" = true))]
4229 #[serde(default)]
4230 pub close: Option<SessionCloseCapabilities>,
4231 #[serde_as(deserialize_as = "DefaultOnError")]
4237 #[schemars(extend("x-deserialize-default-on-error" = true))]
4238 #[serde(default)]
4239 #[serde(rename = "_meta")]
4240 pub meta: Option<Meta>,
4241}
4242
4243impl SessionCapabilities {
4244 #[must_use]
4246 pub fn new() -> Self {
4247 Self::default()
4248 }
4249
4250 #[must_use]
4255 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4256 self.list = list.into_option();
4257 self
4258 }
4259
4260 #[must_use]
4265 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4266 self.delete = delete.into_option();
4267 self
4268 }
4269
4270 #[must_use]
4280 pub fn additional_directories(
4281 mut self,
4282 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4283 ) -> Self {
4284 self.additional_directories = additional_directories.into_option();
4285 self
4286 }
4287
4288 #[cfg(feature = "unstable_session_fork")]
4289 #[must_use]
4294 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4295 self.fork = fork.into_option();
4296 self
4297 }
4298
4299 #[must_use]
4304 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4305 self.resume = resume.into_option();
4306 self
4307 }
4308
4309 #[must_use]
4314 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4315 self.close = close.into_option();
4316 self
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#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4337#[non_exhaustive]
4338pub struct SessionListCapabilities {
4339 #[serde_as(deserialize_as = "DefaultOnError")]
4345 #[schemars(extend("x-deserialize-default-on-error" = true))]
4346 #[serde(default)]
4347 #[serde(rename = "_meta")]
4348 pub meta: Option<Meta>,
4349}
4350
4351impl SessionListCapabilities {
4352 #[must_use]
4354 pub fn new() -> Self {
4355 Self::default()
4356 }
4357
4358 #[must_use]
4364 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4365 self.meta = meta.into_option();
4366 self
4367 }
4368}
4369
4370#[serde_as]
4374#[skip_serializing_none]
4375#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4376#[non_exhaustive]
4377pub struct SessionDeleteCapabilities {
4378 #[serde_as(deserialize_as = "DefaultOnError")]
4384 #[schemars(extend("x-deserialize-default-on-error" = true))]
4385 #[serde(default)]
4386 #[serde(rename = "_meta")]
4387 pub meta: Option<Meta>,
4388}
4389
4390impl SessionDeleteCapabilities {
4391 #[must_use]
4393 pub fn new() -> Self {
4394 Self::default()
4395 }
4396
4397 #[must_use]
4403 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4404 self.meta = meta.into_option();
4405 self
4406 }
4407}
4408
4409#[serde_as]
4416#[skip_serializing_none]
4417#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4418#[non_exhaustive]
4419pub struct SessionAdditionalDirectoriesCapabilities {
4420 #[serde_as(deserialize_as = "DefaultOnError")]
4426 #[schemars(extend("x-deserialize-default-on-error" = true))]
4427 #[serde(default)]
4428 #[serde(rename = "_meta")]
4429 pub meta: Option<Meta>,
4430}
4431
4432impl SessionAdditionalDirectoriesCapabilities {
4433 #[must_use]
4435 pub fn new() -> Self {
4436 Self::default()
4437 }
4438
4439 #[must_use]
4445 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4446 self.meta = meta.into_option();
4447 self
4448 }
4449}
4450
4451#[cfg(feature = "unstable_session_fork")]
4459#[serde_as]
4460#[skip_serializing_none]
4461#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4462#[non_exhaustive]
4463pub struct SessionForkCapabilities {
4464 #[serde_as(deserialize_as = "DefaultOnError")]
4470 #[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_session_fork")]
4477impl SessionForkCapabilities {
4478 #[must_use]
4480 pub fn new() -> Self {
4481 Self::default()
4482 }
4483
4484 #[must_use]
4490 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4491 self.meta = meta.into_option();
4492 self
4493 }
4494}
4495
4496#[serde_as]
4500#[skip_serializing_none]
4501#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4502#[non_exhaustive]
4503pub struct SessionResumeCapabilities {
4504 #[serde_as(deserialize_as = "DefaultOnError")]
4510 #[schemars(extend("x-deserialize-default-on-error" = true))]
4511 #[serde(default)]
4512 #[serde(rename = "_meta")]
4513 pub meta: Option<Meta>,
4514}
4515
4516impl SessionResumeCapabilities {
4517 #[must_use]
4519 pub fn new() -> Self {
4520 Self::default()
4521 }
4522
4523 #[must_use]
4529 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4530 self.meta = meta.into_option();
4531 self
4532 }
4533}
4534
4535#[serde_as]
4539#[skip_serializing_none]
4540#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4541#[non_exhaustive]
4542pub struct SessionCloseCapabilities {
4543 #[serde_as(deserialize_as = "DefaultOnError")]
4549 #[schemars(extend("x-deserialize-default-on-error" = true))]
4550 #[serde(default)]
4551 #[serde(rename = "_meta")]
4552 pub meta: Option<Meta>,
4553}
4554
4555impl SessionCloseCapabilities {
4556 #[must_use]
4558 pub fn new() -> Self {
4559 Self::default()
4560 }
4561
4562 #[must_use]
4568 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4569 self.meta = meta.into_option();
4570 self
4571 }
4572}
4573
4574#[serde_as]
4587#[skip_serializing_none]
4588#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4589#[serde(rename_all = "camelCase")]
4590#[non_exhaustive]
4591pub struct PromptCapabilities {
4592 #[serde_as(deserialize_as = "DefaultOnError")]
4594 #[schemars(extend("x-deserialize-default-on-error" = true))]
4595 #[serde(default)]
4596 pub image: bool,
4597 #[serde_as(deserialize_as = "DefaultOnError")]
4599 #[schemars(extend("x-deserialize-default-on-error" = true))]
4600 #[serde(default)]
4601 pub audio: bool,
4602 #[serde_as(deserialize_as = "DefaultOnError")]
4607 #[schemars(extend("x-deserialize-default-on-error" = true))]
4608 #[serde(default)]
4609 pub embedded_context: bool,
4610 #[serde_as(deserialize_as = "DefaultOnError")]
4616 #[schemars(extend("x-deserialize-default-on-error" = true))]
4617 #[serde(default)]
4618 #[serde(rename = "_meta")]
4619 pub meta: Option<Meta>,
4620}
4621
4622impl PromptCapabilities {
4623 #[must_use]
4625 pub fn new() -> Self {
4626 Self::default()
4627 }
4628
4629 #[must_use]
4631 pub fn image(mut self, image: bool) -> Self {
4632 self.image = image;
4633 self
4634 }
4635
4636 #[must_use]
4638 pub fn audio(mut self, audio: bool) -> Self {
4639 self.audio = audio;
4640 self
4641 }
4642
4643 #[must_use]
4648 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4649 self.embedded_context = embedded_context;
4650 self
4651 }
4652
4653 #[must_use]
4659 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4660 self.meta = meta.into_option();
4661 self
4662 }
4663}
4664
4665#[serde_as]
4667#[skip_serializing_none]
4668#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4669#[serde(rename_all = "camelCase")]
4670#[non_exhaustive]
4671pub struct McpCapabilities {
4672 #[serde_as(deserialize_as = "DefaultOnError")]
4674 #[schemars(extend("x-deserialize-default-on-error" = true))]
4675 #[serde(default)]
4676 pub http: bool,
4677 #[serde_as(deserialize_as = "DefaultOnError")]
4679 #[schemars(extend("x-deserialize-default-on-error" = true))]
4680 #[serde(default)]
4681 pub sse: bool,
4682 #[cfg(feature = "unstable_mcp_over_acp")]
4688 #[serde_as(deserialize_as = "DefaultOnError")]
4689 #[schemars(extend("x-deserialize-default-on-error" = true))]
4690 #[serde(default)]
4691 pub acp: bool,
4692 #[serde_as(deserialize_as = "DefaultOnError")]
4698 #[schemars(extend("x-deserialize-default-on-error" = true))]
4699 #[serde(default)]
4700 #[serde(rename = "_meta")]
4701 pub meta: Option<Meta>,
4702}
4703
4704impl McpCapabilities {
4705 #[must_use]
4707 pub fn new() -> Self {
4708 Self::default()
4709 }
4710
4711 #[must_use]
4713 pub fn http(mut self, http: bool) -> Self {
4714 self.http = http;
4715 self
4716 }
4717
4718 #[must_use]
4720 pub fn sse(mut self, sse: bool) -> Self {
4721 self.sse = sse;
4722 self
4723 }
4724
4725 #[cfg(feature = "unstable_mcp_over_acp")]
4731 #[must_use]
4732 pub fn acp(mut self, acp: bool) -> Self {
4733 self.acp = acp;
4734 self
4735 }
4736
4737 #[must_use]
4743 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4744 self.meta = meta.into_option();
4745 self
4746 }
4747}
4748
4749#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4755#[non_exhaustive]
4756pub struct AgentMethodNames {
4757 pub initialize: &'static str,
4759 pub authenticate: &'static str,
4761 #[cfg(feature = "unstable_llm_providers")]
4763 pub providers_list: &'static str,
4764 #[cfg(feature = "unstable_llm_providers")]
4766 pub providers_set: &'static str,
4767 #[cfg(feature = "unstable_llm_providers")]
4769 pub providers_disable: &'static str,
4770 pub session_new: &'static str,
4772 pub session_load: &'static str,
4774 pub session_set_mode: &'static str,
4776 pub session_set_config_option: &'static str,
4778 pub session_prompt: &'static str,
4780 pub session_cancel: &'static str,
4782 #[cfg(feature = "unstable_mcp_over_acp")]
4784 pub mcp_message: &'static str,
4785 pub session_list: &'static str,
4787 pub session_delete: &'static str,
4789 #[cfg(feature = "unstable_session_fork")]
4791 pub session_fork: &'static str,
4792 pub session_resume: &'static str,
4794 pub session_close: &'static str,
4796 pub logout: &'static str,
4798 #[cfg(feature = "unstable_nes")]
4800 pub nes_start: &'static str,
4801 #[cfg(feature = "unstable_nes")]
4803 pub nes_suggest: &'static str,
4804 #[cfg(feature = "unstable_nes")]
4806 pub nes_accept: &'static str,
4807 #[cfg(feature = "unstable_nes")]
4809 pub nes_reject: &'static str,
4810 #[cfg(feature = "unstable_nes")]
4812 pub nes_close: &'static str,
4813 #[cfg(feature = "unstable_nes")]
4815 pub document_did_open: &'static str,
4816 #[cfg(feature = "unstable_nes")]
4818 pub document_did_change: &'static str,
4819 #[cfg(feature = "unstable_nes")]
4821 pub document_did_close: &'static str,
4822 #[cfg(feature = "unstable_nes")]
4824 pub document_did_save: &'static str,
4825 #[cfg(feature = "unstable_nes")]
4827 pub document_did_focus: &'static str,
4828}
4829
4830pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4832 initialize: INITIALIZE_METHOD_NAME,
4833 authenticate: AUTHENTICATE_METHOD_NAME,
4834 #[cfg(feature = "unstable_llm_providers")]
4835 providers_list: PROVIDERS_LIST_METHOD_NAME,
4836 #[cfg(feature = "unstable_llm_providers")]
4837 providers_set: PROVIDERS_SET_METHOD_NAME,
4838 #[cfg(feature = "unstable_llm_providers")]
4839 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4840 session_new: SESSION_NEW_METHOD_NAME,
4841 session_load: SESSION_LOAD_METHOD_NAME,
4842 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4843 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4844 session_prompt: SESSION_PROMPT_METHOD_NAME,
4845 session_cancel: SESSION_CANCEL_METHOD_NAME,
4846 #[cfg(feature = "unstable_mcp_over_acp")]
4847 mcp_message: MCP_MESSAGE_METHOD_NAME,
4848 session_list: SESSION_LIST_METHOD_NAME,
4849 session_delete: SESSION_DELETE_METHOD_NAME,
4850 #[cfg(feature = "unstable_session_fork")]
4851 session_fork: SESSION_FORK_METHOD_NAME,
4852 session_resume: SESSION_RESUME_METHOD_NAME,
4853 session_close: SESSION_CLOSE_METHOD_NAME,
4854 logout: LOGOUT_METHOD_NAME,
4855 #[cfg(feature = "unstable_nes")]
4856 nes_start: NES_START_METHOD_NAME,
4857 #[cfg(feature = "unstable_nes")]
4858 nes_suggest: NES_SUGGEST_METHOD_NAME,
4859 #[cfg(feature = "unstable_nes")]
4860 nes_accept: NES_ACCEPT_METHOD_NAME,
4861 #[cfg(feature = "unstable_nes")]
4862 nes_reject: NES_REJECT_METHOD_NAME,
4863 #[cfg(feature = "unstable_nes")]
4864 nes_close: NES_CLOSE_METHOD_NAME,
4865 #[cfg(feature = "unstable_nes")]
4866 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4867 #[cfg(feature = "unstable_nes")]
4868 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4869 #[cfg(feature = "unstable_nes")]
4870 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4871 #[cfg(feature = "unstable_nes")]
4872 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4873 #[cfg(feature = "unstable_nes")]
4874 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4875};
4876
4877pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4879pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4881#[cfg(feature = "unstable_llm_providers")]
4883pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4884#[cfg(feature = "unstable_llm_providers")]
4886pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4887#[cfg(feature = "unstable_llm_providers")]
4889pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4890pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4892pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4894pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4896pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4898pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4900pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4902pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4904pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4906#[cfg(feature = "unstable_session_fork")]
4908pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4909pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4911pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4913pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4915
4916#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4923#[serde(untagged)]
4924#[schemars(inline)]
4925#[non_exhaustive]
4926#[allow(clippy::large_enum_variant)]
4927pub enum ClientRequest {
4928 InitializeRequest(InitializeRequest),
4939 AuthenticateRequest(AuthenticateRequest),
4949 #[cfg(feature = "unstable_llm_providers")]
4955 ListProvidersRequest(ListProvidersRequest),
4956 #[cfg(feature = "unstable_llm_providers")]
4962 SetProviderRequest(SetProviderRequest),
4963 #[cfg(feature = "unstable_llm_providers")]
4969 DisableProviderRequest(DisableProviderRequest),
4970 LogoutRequest(LogoutRequest),
4975 NewSessionRequest(NewSessionRequest),
4988 LoadSessionRequest(LoadSessionRequest),
4999 ListSessionsRequest(ListSessionsRequest),
5005 DeleteSessionRequest(DeleteSessionRequest),
5009 #[cfg(feature = "unstable_session_fork")]
5010 ForkSessionRequest(ForkSessionRequest),
5022 ResumeSessionRequest(ResumeSessionRequest),
5029 CloseSessionRequest(CloseSessionRequest),
5036 SetSessionModeRequest(SetSessionModeRequest),
5050 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5052 PromptRequest(PromptRequest),
5064 #[cfg(feature = "unstable_nes")]
5065 StartNesRequest(StartNesRequest),
5071 #[cfg(feature = "unstable_nes")]
5072 SuggestNesRequest(SuggestNesRequest),
5078 #[cfg(feature = "unstable_nes")]
5079 CloseNesRequest(CloseNesRequest),
5088 #[cfg(feature = "unstable_mcp_over_acp")]
5094 MessageMcpRequest(MessageMcpRequest),
5095 ExtMethodRequest(ExtRequest),
5102}
5103
5104impl ClientRequest {
5105 #[must_use]
5107 pub fn method(&self) -> &str {
5108 match self {
5109 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5110 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5111 #[cfg(feature = "unstable_llm_providers")]
5112 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5113 #[cfg(feature = "unstable_llm_providers")]
5114 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
5115 #[cfg(feature = "unstable_llm_providers")]
5116 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5117 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5118 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5119 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5120 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5121 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5122 #[cfg(feature = "unstable_session_fork")]
5123 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5124 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5125 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5126 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
5127 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5128 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5129 #[cfg(feature = "unstable_nes")]
5130 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5131 #[cfg(feature = "unstable_nes")]
5132 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5133 #[cfg(feature = "unstable_nes")]
5134 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5135 #[cfg(feature = "unstable_mcp_over_acp")]
5136 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5137 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5138 }
5139 }
5140}
5141
5142#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5149#[serde(untagged)]
5150#[schemars(inline)]
5151#[non_exhaustive]
5152#[allow(clippy::large_enum_variant)]
5153pub enum AgentResponse {
5154 InitializeResponse(InitializeResponse),
5156 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5158 #[cfg(feature = "unstable_llm_providers")]
5160 ListProvidersResponse(ListProvidersResponse),
5161 #[cfg(feature = "unstable_llm_providers")]
5163 SetProviderResponse(#[serde(default)] SetProviderResponse),
5164 #[cfg(feature = "unstable_llm_providers")]
5166 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5167 LogoutResponse(#[serde(default)] LogoutResponse),
5169 NewSessionResponse(NewSessionResponse),
5171 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5173 ListSessionsResponse(ListSessionsResponse),
5175 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5177 #[cfg(feature = "unstable_session_fork")]
5179 ForkSessionResponse(ForkSessionResponse),
5180 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5182 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5184 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5186 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5188 PromptResponse(PromptResponse),
5190 #[cfg(feature = "unstable_nes")]
5192 StartNesResponse(StartNesResponse),
5193 #[cfg(feature = "unstable_nes")]
5195 SuggestNesResponse(SuggestNesResponse),
5196 #[cfg(feature = "unstable_nes")]
5198 CloseNesResponse(#[serde(default)] CloseNesResponse),
5199 ExtMethodResponse(ExtResponse),
5201 #[cfg(feature = "unstable_mcp_over_acp")]
5203 MessageMcpResponse(MessageMcpResponse),
5204}
5205
5206#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5213#[serde(untagged)]
5214#[schemars(inline)]
5215#[non_exhaustive]
5216#[allow(clippy::large_enum_variant)]
5217pub enum ClientNotification {
5218 CancelNotification(CancelNotification),
5230 #[cfg(feature = "unstable_nes")]
5231 DidOpenDocumentNotification(DidOpenDocumentNotification),
5235 #[cfg(feature = "unstable_nes")]
5236 DidChangeDocumentNotification(DidChangeDocumentNotification),
5240 #[cfg(feature = "unstable_nes")]
5241 DidCloseDocumentNotification(DidCloseDocumentNotification),
5245 #[cfg(feature = "unstable_nes")]
5246 DidSaveDocumentNotification(DidSaveDocumentNotification),
5250 #[cfg(feature = "unstable_nes")]
5251 DidFocusDocumentNotification(DidFocusDocumentNotification),
5255 #[cfg(feature = "unstable_nes")]
5256 AcceptNesNotification(AcceptNesNotification),
5260 #[cfg(feature = "unstable_nes")]
5261 RejectNesNotification(RejectNesNotification),
5265 #[cfg(feature = "unstable_mcp_over_acp")]
5271 MessageMcpNotification(MessageMcpNotification),
5272 ExtNotification(ExtNotification),
5279}
5280
5281impl ClientNotification {
5282 #[must_use]
5284 pub fn method(&self) -> &str {
5285 match self {
5286 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5287 #[cfg(feature = "unstable_nes")]
5288 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5289 #[cfg(feature = "unstable_nes")]
5290 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5291 #[cfg(feature = "unstable_nes")]
5292 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5293 #[cfg(feature = "unstable_nes")]
5294 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5295 #[cfg(feature = "unstable_nes")]
5296 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5297 #[cfg(feature = "unstable_nes")]
5298 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5299 #[cfg(feature = "unstable_nes")]
5300 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5301 #[cfg(feature = "unstable_mcp_over_acp")]
5302 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5303 Self::ExtNotification(ext_notification) => &ext_notification.method,
5304 }
5305 }
5306}
5307
5308#[serde_as]
5312#[skip_serializing_none]
5313#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5314#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5315#[serde(rename_all = "camelCase")]
5316#[non_exhaustive]
5317pub struct CancelNotification {
5318 pub session_id: SessionId,
5320 #[serde_as(deserialize_as = "DefaultOnError")]
5326 #[schemars(extend("x-deserialize-default-on-error" = true))]
5327 #[serde(default)]
5328 #[serde(rename = "_meta")]
5329 pub meta: Option<Meta>,
5330}
5331
5332impl CancelNotification {
5333 #[must_use]
5335 pub fn new(session_id: impl Into<SessionId>) -> Self {
5336 Self {
5337 session_id: session_id.into(),
5338 meta: None,
5339 }
5340 }
5341
5342 #[must_use]
5348 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5349 self.meta = meta.into_option();
5350 self
5351 }
5352}
5353
5354#[cfg(test)]
5355mod test_serialization {
5356 use super::*;
5357 use serde_json::json;
5358
5359 fn test_meta() -> Meta {
5360 json!({ "source": "test" }).as_object().unwrap().clone()
5361 }
5362
5363 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5364 serde_json::to_string(value)
5365 .unwrap()
5366 .matches("\"_meta\"")
5367 .count()
5368 }
5369
5370 #[test]
5371 fn test_initialize_capabilities_default_on_malformed_values() {
5372 let request: InitializeRequest = serde_json::from_value(json!({
5373 "protocolVersion": 1,
5374 "clientCapabilities": false
5375 }))
5376 .unwrap();
5377 assert_eq!(request.client_capabilities, ClientCapabilities::default());
5378
5379 let response: InitializeResponse = serde_json::from_value(json!({
5380 "protocolVersion": 1,
5381 "agentCapabilities": false
5382 }))
5383 .unwrap();
5384 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
5385 }
5386
5387 #[test]
5388 fn test_agent_capabilities_default_on_malformed_values() {
5389 let capabilities: AgentCapabilities = serde_json::from_value(json!({
5390 "loadSession": "yes",
5391 "promptCapabilities": {
5392 "image": "yes",
5393 "audio": true,
5394 "embeddedContext": {}
5395 },
5396 "mcpCapabilities": {
5397 "http": "yes",
5398 "sse": true
5399 },
5400 "sessionCapabilities": false,
5401 "auth": false
5402 }))
5403 .unwrap();
5404
5405 assert!(!capabilities.load_session);
5406 assert!(!capabilities.prompt_capabilities.image);
5407 assert!(capabilities.prompt_capabilities.audio);
5408 assert!(!capabilities.prompt_capabilities.embedded_context);
5409 assert!(!capabilities.mcp_capabilities.http);
5410 assert!(capabilities.mcp_capabilities.sse);
5411 assert_eq!(
5412 capabilities.session_capabilities,
5413 SessionCapabilities::default()
5414 );
5415 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
5416 }
5417
5418 #[test]
5419 fn test_mcp_server_stdio_serialization() {
5420 let server = McpServer::Stdio(
5421 McpServerStdio::new("test-server", "/usr/bin/server")
5422 .args(vec!["--port".to_string(), "3000".to_string()])
5423 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5424 );
5425
5426 let json = serde_json::to_value(&server).unwrap();
5427 assert_eq!(
5428 json,
5429 json!({
5430 "name": "test-server",
5431 "command": "/usr/bin/server",
5432 "args": ["--port", "3000"],
5433 "env": [
5434 {
5435 "name": "API_KEY",
5436 "value": "secret123"
5437 }
5438 ]
5439 })
5440 );
5441
5442 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5443 match deserialized {
5444 McpServer::Stdio(McpServerStdio {
5445 name,
5446 command,
5447 args,
5448 env,
5449 meta: _,
5450 }) => {
5451 assert_eq!(name, "test-server");
5452 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5453 assert_eq!(args, vec!["--port", "3000"]);
5454 assert_eq!(env.len(), 1);
5455 assert_eq!(env[0].name, "API_KEY");
5456 assert_eq!(env[0].value, "secret123");
5457 }
5458 _ => panic!("Expected Stdio variant"),
5459 }
5460 }
5461
5462 #[test]
5463 fn test_mcp_server_http_serialization() {
5464 let server = McpServer::Http(
5465 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5466 HttpHeader::new("Authorization", "Bearer token123"),
5467 HttpHeader::new("Content-Type", "application/json"),
5468 ]),
5469 );
5470
5471 let json = serde_json::to_value(&server).unwrap();
5472 assert_eq!(
5473 json,
5474 json!({
5475 "type": "http",
5476 "name": "http-server",
5477 "url": "https://api.example.com",
5478 "headers": [
5479 {
5480 "name": "Authorization",
5481 "value": "Bearer token123"
5482 },
5483 {
5484 "name": "Content-Type",
5485 "value": "application/json"
5486 }
5487 ]
5488 })
5489 );
5490
5491 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5492 match deserialized {
5493 McpServer::Http(McpServerHttp {
5494 name,
5495 url,
5496 headers,
5497 meta: _,
5498 }) => {
5499 assert_eq!(name, "http-server");
5500 assert_eq!(url, "https://api.example.com");
5501 assert_eq!(headers.len(), 2);
5502 assert_eq!(headers[0].name, "Authorization");
5503 assert_eq!(headers[0].value, "Bearer token123");
5504 assert_eq!(headers[1].name, "Content-Type");
5505 assert_eq!(headers[1].value, "application/json");
5506 }
5507 _ => panic!("Expected Http variant"),
5508 }
5509 }
5510
5511 #[cfg(feature = "unstable_mcp_over_acp")]
5512 #[test]
5513 fn test_mcp_server_acp_serialization() {
5514 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5515
5516 let json = serde_json::to_value(&server).unwrap();
5517 assert_eq!(
5518 json,
5519 json!({
5520 "type": "acp",
5521 "name": "project-tools",
5522 "serverId": "project-tools-id"
5523 })
5524 );
5525
5526 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5527 match deserialized {
5528 McpServer::Acp(McpServerAcp {
5529 name,
5530 server_id: id,
5531 meta: _,
5532 }) => {
5533 assert_eq!(name, "project-tools");
5534 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5535 }
5536 _ => panic!("Expected Acp variant"),
5537 }
5538 }
5539
5540 #[cfg(feature = "unstable_mcp_over_acp")]
5541 #[test]
5542 fn test_client_mcp_message_method_names() {
5543 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5544
5545 assert_eq!(
5546 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5547 .method(),
5548 "mcp/message"
5549 );
5550 assert_eq!(
5551 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5552 "conn-1",
5553 "notifications/progress"
5554 ))
5555 .method(),
5556 "mcp/message"
5557 );
5558 }
5559
5560 #[cfg(feature = "unstable_mcp_over_acp")]
5561 #[test]
5562 fn test_mcp_server_acp_schema() {
5563 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5564 assert!(json_contains_entry(
5565 &mcp_server_schema,
5566 "const",
5567 &json!("acp")
5568 ));
5569 assert!(json_contains_entry(
5570 &mcp_server_schema,
5571 "$ref",
5572 &json!("#/$defs/McpServerAcp")
5573 ));
5574
5575 let capabilities_schema =
5576 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5577 assert!(json_contains_key(&capabilities_schema, "acp"));
5578 }
5579
5580 #[cfg(feature = "unstable_mcp_over_acp")]
5581 fn json_contains_entry(
5582 value: &serde_json::Value,
5583 key: &str,
5584 expected: &serde_json::Value,
5585 ) -> bool {
5586 match value {
5587 serde_json::Value::Object(map) => {
5588 map.get(key) == Some(expected)
5589 || map
5590 .values()
5591 .any(|value| json_contains_entry(value, key, expected))
5592 }
5593 serde_json::Value::Array(values) => values
5594 .iter()
5595 .any(|value| json_contains_entry(value, key, expected)),
5596 _ => false,
5597 }
5598 }
5599
5600 #[cfg(feature = "unstable_mcp_over_acp")]
5601 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5602 match value {
5603 serde_json::Value::Object(map) => {
5604 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5605 }
5606 serde_json::Value::Array(values) => {
5607 values.iter().any(|value| json_contains_key(value, key))
5608 }
5609 _ => false,
5610 }
5611 }
5612
5613 #[test]
5614 fn test_mcp_server_sse_serialization() {
5615 let server = McpServer::Sse(
5616 McpServerSse::new("sse-server", "https://sse.example.com/events")
5617 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5618 );
5619
5620 let json = serde_json::to_value(&server).unwrap();
5621 assert_eq!(
5622 json,
5623 json!({
5624 "type": "sse",
5625 "name": "sse-server",
5626 "url": "https://sse.example.com/events",
5627 "headers": [
5628 {
5629 "name": "X-API-Key",
5630 "value": "apikey456"
5631 }
5632 ]
5633 })
5634 );
5635
5636 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5637 match deserialized {
5638 McpServer::Sse(McpServerSse {
5639 name,
5640 url,
5641 headers,
5642 meta: _,
5643 }) => {
5644 assert_eq!(name, "sse-server");
5645 assert_eq!(url, "https://sse.example.com/events");
5646 assert_eq!(headers.len(), 1);
5647 assert_eq!(headers[0].name, "X-API-Key");
5648 assert_eq!(headers[0].value, "apikey456");
5649 }
5650 _ => panic!("Expected Sse variant"),
5651 }
5652 }
5653
5654 #[test]
5655 fn test_session_config_option_category_known_variants() {
5656 assert_eq!(
5658 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5659 json!("mode")
5660 );
5661 assert_eq!(
5662 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5663 json!("model")
5664 );
5665 assert_eq!(
5666 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5667 json!("model_config")
5668 );
5669 assert_eq!(
5670 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5671 json!("thought_level")
5672 );
5673
5674 assert_eq!(
5676 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5677 SessionConfigOptionCategory::Mode
5678 );
5679 assert_eq!(
5680 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5681 SessionConfigOptionCategory::Model
5682 );
5683 assert_eq!(
5684 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5685 SessionConfigOptionCategory::ModelConfig
5686 );
5687 assert_eq!(
5688 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5689 SessionConfigOptionCategory::ThoughtLevel
5690 );
5691 }
5692
5693 #[test]
5694 fn test_session_config_option_category_unknown_variants() {
5695 let unknown: SessionConfigOptionCategory =
5697 serde_json::from_str("\"some_future_category\"").unwrap();
5698 assert_eq!(
5699 unknown,
5700 SessionConfigOptionCategory::Other("some_future_category".to_string())
5701 );
5702
5703 let json = serde_json::to_value(&unknown).unwrap();
5705 assert_eq!(json, json!("some_future_category"));
5706 }
5707
5708 #[test]
5709 fn test_session_config_option_category_custom_categories() {
5710 let custom: SessionConfigOptionCategory =
5712 serde_json::from_str("\"_my_custom_category\"").unwrap();
5713 assert_eq!(
5714 custom,
5715 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5716 );
5717
5718 let json = serde_json::to_value(&custom).unwrap();
5720 assert_eq!(json, json!("_my_custom_category"));
5721
5722 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5724 assert_eq!(
5725 deserialized,
5726 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5727 );
5728 }
5729
5730 #[test]
5731 fn test_auth_method_agent_serialization() {
5732 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5733
5734 let json = serde_json::to_value(&method).unwrap();
5735 assert_eq!(
5736 json,
5737 json!({
5738 "id": "default-auth",
5739 "name": "Default Auth"
5740 })
5741 );
5742 assert!(!json.as_object().unwrap().contains_key("description"));
5744 assert!(!json.as_object().unwrap().contains_key("type"));
5746
5747 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5748 match deserialized {
5749 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5750 assert_eq!(id.0.as_ref(), "default-auth");
5751 assert_eq!(name, "Default Auth");
5752 }
5753 #[cfg(feature = "unstable_auth_methods")]
5754 _ => panic!("Expected Agent variant"),
5755 }
5756 }
5757
5758 #[test]
5759 fn test_auth_method_explicit_agent_deserialization() {
5760 let json = json!({
5762 "id": "agent-auth",
5763 "name": "Agent Auth",
5764 "type": "agent"
5765 });
5766
5767 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5768 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5769 }
5770
5771 #[test]
5772 fn test_session_delete_serialization() {
5773 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5774 assert_eq!(
5775 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5776 "session/delete"
5777 );
5778 assert_eq!(
5779 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5780 json!({
5781 "sessionId": "sess_abc123"
5782 })
5783 );
5784 assert_eq!(
5785 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5786 json!({})
5787 );
5788 assert_eq!(
5789 serde_json::to_value(
5790 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5791 )
5792 .unwrap(),
5793 json!({
5794 "delete": {}
5795 })
5796 );
5797 }
5798 #[test]
5799 fn test_session_additional_directories_serialization() {
5800 assert_eq!(
5801 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5802 json!({
5803 "cwd": "/home/user/project",
5804 "mcpServers": []
5805 })
5806 );
5807 assert_eq!(
5808 serde_json::to_value(
5809 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5810 PathBuf::from("/home/user/shared-lib"),
5811 PathBuf::from("/home/user/product-docs"),
5812 ])
5813 )
5814 .unwrap(),
5815 json!({
5816 "cwd": "/home/user/project",
5817 "additionalDirectories": [
5818 "/home/user/shared-lib",
5819 "/home/user/product-docs"
5820 ],
5821 "mcpServers": []
5822 })
5823 );
5824 assert_eq!(
5825 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5826 json!({
5827 "sessionId": "sess_abc123",
5828 "cwd": "/home/user/project"
5829 })
5830 );
5831 assert_eq!(
5832 serde_json::to_value(
5833 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5834 PathBuf::from("/home/user/shared-lib"),
5835 PathBuf::from("/home/user/product-docs"),
5836 ])
5837 )
5838 .unwrap(),
5839 json!({
5840 "sessionId": "sess_abc123",
5841 "cwd": "/home/user/project",
5842 "additionalDirectories": [
5843 "/home/user/shared-lib",
5844 "/home/user/product-docs"
5845 ]
5846 })
5847 );
5848 assert_eq!(
5849 serde_json::from_value::<SessionInfo>(json!({
5850 "sessionId": "sess_abc123",
5851 "cwd": "/home/user/project"
5852 }))
5853 .unwrap()
5854 .additional_directories,
5855 Vec::<PathBuf>::new()
5856 );
5857 }
5858 #[test]
5859 fn test_session_additional_directories_capabilities_serialization() {
5860 assert_eq!(
5861 serde_json::to_value(
5862 SessionCapabilities::new()
5863 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5864 )
5865 .unwrap(),
5866 json!({
5867 "additionalDirectories": {}
5868 })
5869 );
5870 }
5871
5872 #[cfg(feature = "unstable_auth_methods")]
5873 #[test]
5874 fn test_auth_method_env_var_serialization() {
5875 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5876 "api-key",
5877 "API Key",
5878 vec![AuthEnvVar::new("API_KEY")],
5879 ));
5880
5881 let json = serde_json::to_value(&method).unwrap();
5882 assert_eq!(
5883 json,
5884 json!({
5885 "id": "api-key",
5886 "name": "API Key",
5887 "type": "env_var",
5888 "vars": [{"name": "API_KEY"}]
5889 })
5890 );
5891 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5893 assert!(
5894 !json["vars"][0]
5895 .as_object()
5896 .unwrap()
5897 .contains_key("optional")
5898 );
5899
5900 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5901 match deserialized {
5902 AuthMethod::EnvVar(AuthMethodEnvVar {
5903 id,
5904 name: method_name,
5905 vars,
5906 link,
5907 ..
5908 }) => {
5909 assert_eq!(id.0.as_ref(), "api-key");
5910 assert_eq!(method_name, "API Key");
5911 assert_eq!(vars.len(), 1);
5912 assert_eq!(vars[0].name, "API_KEY");
5913 assert!(vars[0].secret);
5914 assert!(!vars[0].optional);
5915 assert!(link.is_none());
5916 }
5917 _ => panic!("Expected EnvVar variant"),
5918 }
5919 }
5920
5921 #[cfg(feature = "unstable_auth_methods")]
5922 #[test]
5923 fn test_auth_method_env_var_with_link_serialization() {
5924 let method = AuthMethod::EnvVar(
5925 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5926 .link("https://example.com/keys"),
5927 );
5928
5929 let json = serde_json::to_value(&method).unwrap();
5930 assert_eq!(
5931 json,
5932 json!({
5933 "id": "api-key",
5934 "name": "API Key",
5935 "type": "env_var",
5936 "vars": [{"name": "API_KEY"}],
5937 "link": "https://example.com/keys"
5938 })
5939 );
5940
5941 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5942 match deserialized {
5943 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5944 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5945 }
5946 _ => panic!("Expected EnvVar variant"),
5947 }
5948 }
5949
5950 #[cfg(feature = "unstable_auth_methods")]
5951 #[test]
5952 fn test_auth_method_env_var_multiple_vars() {
5953 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5954 "azure-openai",
5955 "Azure OpenAI",
5956 vec![
5957 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5958 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5959 .label("Endpoint URL")
5960 .secret(false),
5961 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5962 .label("API Version")
5963 .secret(false)
5964 .optional(true),
5965 ],
5966 ));
5967
5968 let json = serde_json::to_value(&method).unwrap();
5969 assert_eq!(
5970 json,
5971 json!({
5972 "id": "azure-openai",
5973 "name": "Azure OpenAI",
5974 "type": "env_var",
5975 "vars": [
5976 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5977 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5978 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5979 ]
5980 })
5981 );
5982
5983 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5984 match deserialized {
5985 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5986 assert_eq!(vars.len(), 3);
5987 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5989 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5990 assert!(vars[0].secret);
5991 assert!(!vars[0].optional);
5992 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5994 assert!(!vars[1].secret);
5995 assert!(!vars[1].optional);
5996 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5998 assert!(!vars[2].secret);
5999 assert!(vars[2].optional);
6000 }
6001 _ => panic!("Expected EnvVar variant"),
6002 }
6003 }
6004
6005 #[cfg(feature = "unstable_auth_methods")]
6006 #[test]
6007 fn test_auth_method_terminal_serialization() {
6008 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
6009
6010 let json = serde_json::to_value(&method).unwrap();
6011 assert_eq!(
6012 json,
6013 json!({
6014 "id": "tui-auth",
6015 "name": "Terminal Auth",
6016 "type": "terminal"
6017 })
6018 );
6019 assert!(!json.as_object().unwrap().contains_key("args"));
6021 assert!(!json.as_object().unwrap().contains_key("env"));
6022
6023 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
6024 match deserialized {
6025 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
6026 assert!(args.is_empty());
6027 assert!(env.is_empty());
6028 }
6029 _ => panic!("Expected Terminal variant"),
6030 }
6031 }
6032
6033 #[cfg(feature = "unstable_auth_methods")]
6034 #[test]
6035 fn test_auth_method_terminal_with_args_and_env_serialization() {
6036 use std::collections::HashMap;
6037
6038 let mut env = HashMap::new();
6039 env.insert("TERM".to_string(), "xterm-256color".to_string());
6040
6041 let method = AuthMethod::Terminal(
6042 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
6043 .args(vec!["--interactive".to_string(), "--color".to_string()])
6044 .env(env),
6045 );
6046
6047 let json = serde_json::to_value(&method).unwrap();
6048 assert_eq!(
6049 json,
6050 json!({
6051 "id": "tui-auth",
6052 "name": "Terminal Auth",
6053 "type": "terminal",
6054 "args": ["--interactive", "--color"],
6055 "env": {
6056 "TERM": "xterm-256color"
6057 }
6058 })
6059 );
6060
6061 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
6062 match deserialized {
6063 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
6064 assert_eq!(args, vec!["--interactive", "--color"]);
6065 assert_eq!(env.len(), 1);
6066 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
6067 }
6068 _ => panic!("Expected Terminal variant"),
6069 }
6070 }
6071
6072 #[test]
6073 fn test_session_config_option_value_id_serialize() {
6074 let val = SessionConfigOptionValue::value_id("model-1");
6075 let json = serde_json::to_value(&val).unwrap();
6076 assert_eq!(json, json!({ "value": "model-1" }));
6078 assert!(!json.as_object().unwrap().contains_key("type"));
6079 }
6080
6081 #[test]
6082 fn test_session_config_option_value_boolean_serialize() {
6083 let val = SessionConfigOptionValue::boolean(true);
6084 let json = serde_json::to_value(&val).unwrap();
6085 assert_eq!(json, json!({ "type": "boolean", "value": true }));
6086 }
6087
6088 #[test]
6089 fn test_session_config_option_value_deserialize_no_type() {
6090 let json = json!({ "value": "model-1" });
6092 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6093 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
6094 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
6095 }
6096
6097 #[test]
6098 fn test_session_config_option_value_deserialize_boolean() {
6099 let json = json!({ "type": "boolean", "value": true });
6100 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6101 assert_eq!(val, SessionConfigOptionValue::boolean(true));
6102 assert_eq!(val.as_bool(), Some(true));
6103 }
6104
6105 #[test]
6106 fn test_session_config_option_value_deserialize_boolean_false() {
6107 let json = json!({ "type": "boolean", "value": false });
6108 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6109 assert_eq!(val, SessionConfigOptionValue::boolean(false));
6110 assert_eq!(val.as_bool(), Some(false));
6111 }
6112
6113 #[test]
6114 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6115 let json = json!({ "type": "text", "value": "freeform input" });
6117 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6118 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6119 }
6120
6121 #[test]
6122 fn test_session_config_option_value_roundtrip_value_id() {
6123 let original = SessionConfigOptionValue::value_id("option-a");
6124 let json = serde_json::to_value(&original).unwrap();
6125 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6126 assert_eq!(original, roundtripped);
6127 }
6128
6129 #[test]
6130 fn test_session_config_option_value_roundtrip_boolean() {
6131 let original = SessionConfigOptionValue::boolean(false);
6132 let json = serde_json::to_value(&original).unwrap();
6133 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6134 assert_eq!(original, roundtripped);
6135 }
6136
6137 #[test]
6138 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6139 let json = json!({ "type": "boolean", "value": "not a bool" });
6141 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6142 assert!(result.is_ok());
6144 assert_eq!(
6145 result.unwrap().as_value_id().unwrap().to_string(),
6146 "not a bool"
6147 );
6148 }
6149
6150 #[test]
6151 fn test_session_config_option_value_from_impls() {
6152 let from_str: SessionConfigOptionValue = "model-1".into();
6153 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6154
6155 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6156 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6157
6158 let from_bool: SessionConfigOptionValue = true.into();
6159 assert_eq!(from_bool.as_bool(), Some(true));
6160 }
6161
6162 #[test]
6163 fn test_set_session_config_option_request_value_id() {
6164 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6165 let json = serde_json::to_value(&req).unwrap();
6166 assert_eq!(
6167 json,
6168 json!({
6169 "sessionId": "sess_1",
6170 "configId": "model",
6171 "value": "model-1"
6172 })
6173 );
6174 assert!(!json.as_object().unwrap().contains_key("type"));
6176 }
6177
6178 #[test]
6179 fn test_set_session_config_option_request_boolean() {
6180 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6181 let json = serde_json::to_value(&req).unwrap();
6182 assert_eq!(
6183 json,
6184 json!({
6185 "sessionId": "sess_1",
6186 "configId": "brave_mode",
6187 "type": "boolean",
6188 "value": true
6189 })
6190 );
6191 }
6192
6193 #[test]
6194 fn test_set_session_config_option_request_deserialize_no_type() {
6195 let json = json!({
6197 "sessionId": "sess_1",
6198 "configId": "model",
6199 "value": "model-1"
6200 });
6201 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6202 assert_eq!(req.session_id.to_string(), "sess_1");
6203 assert_eq!(req.config_id.to_string(), "model");
6204 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6205 }
6206
6207 #[test]
6208 fn test_set_session_config_option_request_deserialize_boolean() {
6209 let json = json!({
6210 "sessionId": "sess_1",
6211 "configId": "brave_mode",
6212 "type": "boolean",
6213 "value": true
6214 });
6215 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6216 assert_eq!(req.value.as_bool(), Some(true));
6217 }
6218
6219 #[test]
6220 fn test_set_session_config_option_request_roundtrip_value_id() {
6221 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6222 let json = serde_json::to_value(&original).unwrap();
6223 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6224 assert_eq!(original, roundtripped);
6225 }
6226
6227 #[test]
6228 fn test_set_session_config_option_request_roundtrip_boolean() {
6229 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6230 let json = serde_json::to_value(&original).unwrap();
6231 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6232 assert_eq!(original, roundtripped);
6233 }
6234
6235 #[test]
6236 fn test_session_config_boolean_serialization() {
6237 let cfg = SessionConfigBoolean::new(true);
6238 let json = serde_json::to_value(&cfg).unwrap();
6239 assert_eq!(json, json!({ "currentValue": true }));
6240
6241 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6242 assert!(deserialized.current_value);
6243 }
6244
6245 #[test]
6246 fn test_session_config_option_boolean_variant() {
6247 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6248 .description("Skip confirmation prompts")
6249 .meta(test_meta());
6250 assert_eq!(serialized_meta_key_count(&opt), 1);
6251
6252 let json = serde_json::to_value(&opt).unwrap();
6253 assert_eq!(
6254 json,
6255 json!({
6256 "id": "brave_mode",
6257 "name": "Brave Mode",
6258 "description": "Skip confirmation prompts",
6259 "type": "boolean",
6260 "currentValue": false,
6261 "_meta": {
6262 "source": "test"
6263 }
6264 })
6265 );
6266
6267 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6268 assert_eq!(deserialized.id.to_string(), "brave_mode");
6269 assert_eq!(deserialized.name, "Brave Mode");
6270 match deserialized.kind {
6271 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6272 _ => panic!("Expected Boolean kind"),
6273 }
6274 }
6275
6276 #[test]
6277 fn test_session_config_option_select_still_works() {
6278 let opt = SessionConfigOption::select(
6280 "model",
6281 "Model",
6282 "model-1",
6283 vec![
6284 SessionConfigSelectOption::new("model-1", "Model 1"),
6285 SessionConfigSelectOption::new("model-2", "Model 2"),
6286 ],
6287 )
6288 .meta(test_meta());
6289 assert_eq!(serialized_meta_key_count(&opt), 1);
6290
6291 let json = serde_json::to_value(&opt).unwrap();
6292 assert_eq!(json["type"], "select");
6293 assert_eq!(json["currentValue"], "model-1");
6294 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6295 assert_eq!(json["_meta"]["source"], "test");
6296
6297 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6298 match deserialized.kind {
6299 SessionConfigKind::Select(ref s) => {
6300 assert_eq!(s.current_value.to_string(), "model-1");
6301 }
6302 _ => panic!("Expected Select kind"),
6303 }
6304 }
6305
6306 #[cfg(feature = "unstable_llm_providers")]
6307 #[test]
6308 fn test_llm_protocol_known_variants() {
6309 assert_eq!(
6310 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6311 json!("anthropic")
6312 );
6313 assert_eq!(
6314 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6315 json!("openai")
6316 );
6317 assert_eq!(
6318 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6319 json!("azure")
6320 );
6321 assert_eq!(
6322 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6323 json!("vertex")
6324 );
6325 assert_eq!(
6326 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6327 json!("bedrock")
6328 );
6329
6330 assert_eq!(
6331 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6332 LlmProtocol::Anthropic
6333 );
6334 assert_eq!(
6335 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6336 LlmProtocol::OpenAi
6337 );
6338 assert_eq!(
6339 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6340 LlmProtocol::Azure
6341 );
6342 assert_eq!(
6343 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6344 LlmProtocol::Vertex
6345 );
6346 assert_eq!(
6347 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6348 LlmProtocol::Bedrock
6349 );
6350 }
6351
6352 #[cfg(feature = "unstable_llm_providers")]
6353 #[test]
6354 fn test_llm_protocol_unknown_variant() {
6355 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6356 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6357
6358 let json = serde_json::to_value(&unknown).unwrap();
6359 assert_eq!(json, json!("cohere"));
6360 }
6361
6362 #[cfg(feature = "unstable_llm_providers")]
6363 #[test]
6364 fn test_provider_current_config_serialization() {
6365 let config =
6366 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6367
6368 let json = serde_json::to_value(&config).unwrap();
6369 assert_eq!(
6370 json,
6371 json!({
6372 "apiType": "anthropic",
6373 "baseUrl": "https://api.anthropic.com"
6374 })
6375 );
6376
6377 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6378 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6379 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6380 }
6381
6382 #[cfg(feature = "unstable_llm_providers")]
6383 #[test]
6384 fn test_provider_info_with_current_config() {
6385 let info = ProviderInfo::new(
6386 "main",
6387 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6388 true,
6389 Some(ProviderCurrentConfig::new(
6390 LlmProtocol::Anthropic,
6391 "https://api.anthropic.com",
6392 )),
6393 );
6394
6395 let json = serde_json::to_value(&info).unwrap();
6396 assert_eq!(
6397 json,
6398 json!({
6399 "providerId": "main",
6400 "supported": ["anthropic", "openai"],
6401 "required": true,
6402 "current": {
6403 "apiType": "anthropic",
6404 "baseUrl": "https://api.anthropic.com"
6405 }
6406 })
6407 );
6408
6409 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6410 assert_eq!(deserialized.provider_id.to_string(), "main");
6411 assert_eq!(deserialized.supported.len(), 2);
6412 assert!(deserialized.required);
6413 assert!(deserialized.current.is_some());
6414 assert_eq!(
6415 deserialized.current.as_ref().unwrap().api_type,
6416 LlmProtocol::Anthropic
6417 );
6418 }
6419
6420 #[cfg(feature = "unstable_llm_providers")]
6421 #[test]
6422 fn test_provider_info_disabled() {
6423 let info = ProviderInfo::new(
6424 "secondary",
6425 vec![LlmProtocol::OpenAi],
6426 false,
6427 None::<ProviderCurrentConfig>,
6428 );
6429
6430 let json = serde_json::to_value(&info).unwrap();
6431 assert_eq!(
6432 json,
6433 json!({
6434 "providerId": "secondary",
6435 "supported": ["openai"],
6436 "required": false
6437 })
6438 );
6439
6440 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6441 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6442 assert!(!deserialized.required);
6443 assert!(deserialized.current.is_none());
6444 }
6445
6446 #[cfg(feature = "unstable_llm_providers")]
6447 #[test]
6448 fn test_provider_info_missing_current_defaults_to_none() {
6449 let json = json!({
6451 "providerId": "main",
6452 "supported": ["anthropic"],
6453 "required": true
6454 });
6455 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6456 assert!(deserialized.current.is_none());
6457 }
6458
6459 #[cfg(feature = "unstable_llm_providers")]
6460 #[test]
6461 fn test_provider_info_explicit_null_current_decodes_to_none() {
6462 let json = json!({
6466 "providerId": "main",
6467 "supported": ["anthropic"],
6468 "required": true,
6469 "current": null
6470 });
6471 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6472 assert!(deserialized.current.is_none());
6473 }
6474
6475 #[cfg(feature = "unstable_llm_providers")]
6476 #[test]
6477 fn test_list_providers_response_serialization() {
6478 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6479 "main",
6480 vec![LlmProtocol::Anthropic],
6481 true,
6482 Some(ProviderCurrentConfig::new(
6483 LlmProtocol::Anthropic,
6484 "https://api.anthropic.com",
6485 )),
6486 )]);
6487
6488 let json = serde_json::to_value(&response).unwrap();
6489 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6490 assert_eq!(json["providers"][0]["providerId"], "main");
6491
6492 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6493 assert_eq!(deserialized.providers.len(), 1);
6494 }
6495
6496 #[cfg(feature = "unstable_llm_providers")]
6497 #[test]
6498 fn test_set_provider_request_serialization() {
6499 use std::collections::HashMap;
6500
6501 let mut headers = HashMap::new();
6502 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6503
6504 let request =
6505 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6506 .headers(headers);
6507
6508 let json = serde_json::to_value(&request).unwrap();
6509 assert_eq!(
6510 json,
6511 json!({
6512 "providerId": "main",
6513 "apiType": "openai",
6514 "baseUrl": "https://api.openai.com/v1",
6515 "headers": {
6516 "Authorization": "Bearer sk-test"
6517 }
6518 })
6519 );
6520
6521 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6522 assert_eq!(deserialized.provider_id.to_string(), "main");
6523 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6524 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6525 assert_eq!(deserialized.headers.len(), 1);
6526 assert_eq!(
6527 deserialized.headers.get("Authorization").unwrap(),
6528 "Bearer sk-test"
6529 );
6530 }
6531
6532 #[cfg(feature = "unstable_llm_providers")]
6533 #[test]
6534 fn test_set_provider_request_omits_empty_headers() {
6535 let request =
6536 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6537
6538 let json = serde_json::to_value(&request).unwrap();
6539 assert!(!json.as_object().unwrap().contains_key("headers"));
6541 }
6542
6543 #[cfg(feature = "unstable_llm_providers")]
6544 #[test]
6545 fn test_disable_provider_request_serialization() {
6546 let request = DisableProviderRequest::new("secondary");
6547
6548 let json = serde_json::to_value(&request).unwrap();
6549 assert_eq!(json, json!({ "providerId": "secondary" }));
6550
6551 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6552 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6553 }
6554
6555 #[cfg(feature = "unstable_llm_providers")]
6556 #[test]
6557 fn test_providers_capabilities_serialization() {
6558 let caps = ProvidersCapabilities::new();
6559
6560 let json = serde_json::to_value(&caps).unwrap();
6561 assert_eq!(json, json!({}));
6562
6563 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6564 assert!(deserialized.meta.is_none());
6565 }
6566
6567 #[cfg(feature = "unstable_llm_providers")]
6568 #[test]
6569 fn test_agent_capabilities_with_providers() {
6570 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6571
6572 let json = serde_json::to_value(&caps).unwrap();
6573 assert_eq!(json["providers"], json!({}));
6574
6575 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6576 assert!(deserialized.providers.is_some());
6577 }
6578
6579 #[test]
6580 fn prompt_request_rejects_malformed_content_block() {
6581 use serde_json::json;
6582
6583 assert!(
6584 serde_json::from_value::<PromptRequest>(json!({
6585 "sessionId": "sess-1",
6586 "prompt": [{"type": "text"}]
6587 }))
6588 .is_err()
6589 );
6590 }
6591
6592 #[test]
6593 fn prompt_request_rejects_non_array_prompt() {
6594 use serde_json::json;
6595
6596 assert!(
6597 serde_json::from_value::<PromptRequest>(json!({
6598 "sessionId": "sess-1",
6599 "prompt": "hello"
6600 }))
6601 .is_err()
6602 );
6603 }
6604}