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")]
465 #[schemars(extend("x-deserialize-default-on-error" = true))]
466 #[serde(default)]
467 pub logout: Option<LogoutCapabilities>,
468 #[serde_as(deserialize_as = "DefaultOnError")]
474 #[schemars(extend("x-deserialize-default-on-error" = true))]
475 #[serde(default)]
476 #[serde(rename = "_meta")]
477 pub meta: Option<Meta>,
478}
479
480impl AgentAuthCapabilities {
481 #[must_use]
483 pub fn new() -> Self {
484 Self::default()
485 }
486
487 #[must_use]
489 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
490 self.logout = logout.into_option();
491 self
492 }
493
494 #[must_use]
500 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
501 self.meta = meta.into_option();
502 self
503 }
504}
505
506#[serde_as]
510#[skip_serializing_none]
511#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
512#[non_exhaustive]
513pub struct LogoutCapabilities {
514 #[serde_as(deserialize_as = "DefaultOnError")]
520 #[schemars(extend("x-deserialize-default-on-error" = true))]
521 #[serde(default)]
522 #[serde(rename = "_meta")]
523 pub meta: Option<Meta>,
524}
525
526impl LogoutCapabilities {
527 #[must_use]
529 pub fn new() -> Self {
530 Self::default()
531 }
532
533 #[must_use]
539 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
540 self.meta = meta.into_option();
541 self
542 }
543}
544
545#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
547#[serde(transparent)]
548#[from(Arc<str>, String, &'static str)]
549#[non_exhaustive]
550pub struct AuthMethodId(pub Arc<str>);
551
552impl AuthMethodId {
553 #[must_use]
555 pub fn new(id: impl Into<Arc<str>>) -> Self {
556 Self(id.into())
557 }
558}
559
560#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
565#[serde(tag = "type", rename_all = "snake_case")]
566#[non_exhaustive]
567pub enum AuthMethod {
568 #[cfg(feature = "unstable_auth_methods")]
574 EnvVar(AuthMethodEnvVar),
575 #[cfg(feature = "unstable_auth_methods")]
581 Terminal(AuthMethodTerminal),
582 #[serde(untagged)]
586 Agent(AuthMethodAgent),
587}
588
589impl AuthMethod {
590 #[must_use]
592 pub fn id(&self) -> &AuthMethodId {
593 match self {
594 Self::Agent(a) => &a.id,
595 #[cfg(feature = "unstable_auth_methods")]
596 Self::EnvVar(e) => &e.id,
597 #[cfg(feature = "unstable_auth_methods")]
598 Self::Terminal(t) => &t.id,
599 }
600 }
601
602 #[must_use]
604 pub fn name(&self) -> &str {
605 match self {
606 Self::Agent(a) => &a.name,
607 #[cfg(feature = "unstable_auth_methods")]
608 Self::EnvVar(e) => &e.name,
609 #[cfg(feature = "unstable_auth_methods")]
610 Self::Terminal(t) => &t.name,
611 }
612 }
613
614 #[must_use]
616 pub fn description(&self) -> Option<&str> {
617 match self {
618 Self::Agent(a) => a.description.as_deref(),
619 #[cfg(feature = "unstable_auth_methods")]
620 Self::EnvVar(e) => e.description.as_deref(),
621 #[cfg(feature = "unstable_auth_methods")]
622 Self::Terminal(t) => t.description.as_deref(),
623 }
624 }
625
626 #[must_use]
632 pub fn meta(&self) -> Option<&Meta> {
633 match self {
634 Self::Agent(a) => a.meta.as_ref(),
635 #[cfg(feature = "unstable_auth_methods")]
636 Self::EnvVar(e) => e.meta.as_ref(),
637 #[cfg(feature = "unstable_auth_methods")]
638 Self::Terminal(t) => t.meta.as_ref(),
639 }
640 }
641}
642
643#[serde_as]
647#[skip_serializing_none]
648#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
649#[serde(rename_all = "camelCase")]
650#[non_exhaustive]
651pub struct AuthMethodAgent {
652 pub id: AuthMethodId,
654 pub name: String,
656 #[serde_as(deserialize_as = "DefaultOnError")]
658 #[schemars(extend("x-deserialize-default-on-error" = true))]
659 #[serde(default)]
660 pub description: Option<String>,
661 #[serde_as(deserialize_as = "DefaultOnError")]
667 #[schemars(extend("x-deserialize-default-on-error" = true))]
668 #[serde(default)]
669 #[serde(rename = "_meta")]
670 pub meta: Option<Meta>,
671}
672
673impl AuthMethodAgent {
674 #[must_use]
676 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
677 Self {
678 id: id.into(),
679 name: name.into(),
680 description: None,
681 meta: None,
682 }
683 }
684
685 #[must_use]
687 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
688 self.description = description.into_option();
689 self
690 }
691
692 #[must_use]
698 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
699 self.meta = meta.into_option();
700 self
701 }
702}
703
704#[cfg(feature = "unstable_auth_methods")]
712#[serde_as]
713#[skip_serializing_none]
714#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
715#[serde(rename_all = "camelCase")]
716#[non_exhaustive]
717pub struct AuthMethodEnvVar {
718 pub id: AuthMethodId,
720 pub name: String,
722 #[serde_as(deserialize_as = "DefaultOnError")]
724 #[schemars(extend("x-deserialize-default-on-error" = true))]
725 #[serde(default)]
726 pub description: Option<String>,
727 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
729 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
730 pub vars: Vec<AuthEnvVar>,
731 #[serde_as(deserialize_as = "DefaultOnError")]
733 #[schemars(extend("x-deserialize-default-on-error" = true))]
734 #[serde(default)]
735 pub link: Option<String>,
736 #[serde_as(deserialize_as = "DefaultOnError")]
742 #[schemars(extend("x-deserialize-default-on-error" = true))]
743 #[serde(default)]
744 #[serde(rename = "_meta")]
745 pub meta: Option<Meta>,
746}
747
748#[cfg(feature = "unstable_auth_methods")]
749impl AuthMethodEnvVar {
750 #[must_use]
752 pub fn new(
753 id: impl Into<AuthMethodId>,
754 name: impl Into<String>,
755 vars: Vec<AuthEnvVar>,
756 ) -> Self {
757 Self {
758 id: id.into(),
759 name: name.into(),
760 description: None,
761 vars,
762 link: None,
763 meta: None,
764 }
765 }
766
767 #[must_use]
769 pub fn link(mut self, link: impl IntoOption<String>) -> Self {
770 self.link = link.into_option();
771 self
772 }
773
774 #[must_use]
776 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
777 self.description = description.into_option();
778 self
779 }
780
781 #[must_use]
787 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
788 self.meta = meta.into_option();
789 self
790 }
791}
792
793#[cfg(feature = "unstable_auth_methods")]
799#[serde_as]
800#[skip_serializing_none]
801#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
802#[serde(rename_all = "camelCase")]
803#[non_exhaustive]
804pub struct AuthEnvVar {
805 pub name: String,
807 #[serde_as(deserialize_as = "DefaultOnError")]
809 #[schemars(extend("x-deserialize-default-on-error" = true))]
810 #[serde(default)]
811 pub label: Option<String>,
812 #[serde_as(deserialize_as = "DefaultTrueOnError")]
817 #[schemars(extend("x-deserialize-default-on-error" = true))]
818 #[serde(default = "default_true", skip_serializing_if = "is_true")]
819 #[schemars(extend("default" = true))]
820 pub secret: bool,
821 #[serde_as(deserialize_as = "DefaultOnError")]
825 #[schemars(extend("x-deserialize-default-on-error" = true))]
826 #[serde(default, skip_serializing_if = "is_false")]
827 #[schemars(extend("default" = false))]
828 pub optional: bool,
829 #[serde_as(deserialize_as = "DefaultOnError")]
835 #[schemars(extend("x-deserialize-default-on-error" = true))]
836 #[serde(default)]
837 #[serde(rename = "_meta")]
838 pub meta: Option<Meta>,
839}
840
841#[cfg(feature = "unstable_auth_methods")]
842fn default_true() -> bool {
843 true
844}
845
846#[cfg(feature = "unstable_auth_methods")]
847#[expect(clippy::trivially_copy_pass_by_ref)]
848fn is_true(v: &bool) -> bool {
849 *v
850}
851
852#[cfg(feature = "unstable_auth_methods")]
853#[expect(clippy::trivially_copy_pass_by_ref)]
854fn is_false(v: &bool) -> bool {
855 !*v
856}
857
858#[cfg(feature = "unstable_auth_methods")]
859impl AuthEnvVar {
860 #[must_use]
862 pub fn new(name: impl Into<String>) -> Self {
863 Self {
864 name: name.into(),
865 label: None,
866 secret: true,
867 optional: false,
868 meta: None,
869 }
870 }
871
872 #[must_use]
874 pub fn label(mut self, label: impl IntoOption<String>) -> Self {
875 self.label = label.into_option();
876 self
877 }
878
879 #[must_use]
882 pub fn secret(mut self, secret: bool) -> Self {
883 self.secret = secret;
884 self
885 }
886
887 #[must_use]
889 pub fn optional(mut self, optional: bool) -> Self {
890 self.optional = optional;
891 self
892 }
893
894 #[must_use]
900 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
901 self.meta = meta.into_option();
902 self
903 }
904}
905
906#[cfg(feature = "unstable_auth_methods")]
914#[serde_as]
915#[skip_serializing_none]
916#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
917#[serde(rename_all = "camelCase")]
918#[non_exhaustive]
919pub struct AuthMethodTerminal {
920 pub id: AuthMethodId,
922 pub name: String,
924 #[serde_as(deserialize_as = "DefaultOnError")]
926 #[schemars(extend("x-deserialize-default-on-error" = true))]
927 #[serde(default)]
928 pub description: Option<String>,
929 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
931 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
932 #[serde(default, skip_serializing_if = "Vec::is_empty")]
933 pub args: Vec<String>,
934 #[serde_as(deserialize_as = "DefaultOnError")]
936 #[schemars(extend("x-deserialize-default-on-error" = true))]
937 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
938 pub env: HashMap<String, String>,
939 #[serde_as(deserialize_as = "DefaultOnError")]
945 #[schemars(extend("x-deserialize-default-on-error" = true))]
946 #[serde(default)]
947 #[serde(rename = "_meta")]
948 pub meta: Option<Meta>,
949}
950
951#[cfg(feature = "unstable_auth_methods")]
952impl AuthMethodTerminal {
953 #[must_use]
955 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
956 Self {
957 id: id.into(),
958 name: name.into(),
959 description: None,
960 args: Vec::new(),
961 env: HashMap::new(),
962 meta: None,
963 }
964 }
965
966 #[must_use]
968 pub fn args(mut self, args: Vec<String>) -> Self {
969 self.args = args;
970 self
971 }
972
973 #[must_use]
975 pub fn env(mut self, env: HashMap<String, String>) -> Self {
976 self.env = env;
977 self
978 }
979
980 #[must_use]
982 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
983 self.description = description.into_option();
984 self
985 }
986
987 #[must_use]
993 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
994 self.meta = meta.into_option();
995 self
996 }
997}
998
999#[serde_as]
1005#[skip_serializing_none]
1006#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1007#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1008#[serde(rename_all = "camelCase")]
1009#[non_exhaustive]
1010pub struct NewSessionRequest {
1011 pub cwd: PathBuf,
1013 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1019 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1020 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1021 pub additional_directories: Vec<PathBuf>,
1022 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1024 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1025 pub mcp_servers: Vec<McpServer>,
1026 #[serde_as(deserialize_as = "DefaultOnError")]
1032 #[schemars(extend("x-deserialize-default-on-error" = true))]
1033 #[serde(default)]
1034 #[serde(rename = "_meta")]
1035 pub meta: Option<Meta>,
1036}
1037
1038impl NewSessionRequest {
1039 #[must_use]
1041 pub fn new(cwd: impl Into<PathBuf>) -> Self {
1042 Self {
1043 cwd: cwd.into(),
1044 additional_directories: vec![],
1045 mcp_servers: vec![],
1046 meta: None,
1047 }
1048 }
1049
1050 #[must_use]
1052 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1053 self.additional_directories = additional_directories;
1054 self
1055 }
1056
1057 #[must_use]
1059 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1060 self.mcp_servers = mcp_servers;
1061 self
1062 }
1063
1064 #[must_use]
1070 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1071 self.meta = meta.into_option();
1072 self
1073 }
1074}
1075
1076#[serde_as]
1080#[skip_serializing_none]
1081#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1082#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1083#[serde(rename_all = "camelCase")]
1084#[non_exhaustive]
1085pub struct NewSessionResponse {
1086 pub session_id: SessionId,
1090 #[serde_as(deserialize_as = "DefaultOnError")]
1094 #[schemars(extend("x-deserialize-default-on-error" = true))]
1095 #[serde(default)]
1096 pub modes: Option<SessionModeState>,
1097 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1099 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1100 #[serde(default)]
1101 pub config_options: Option<Vec<SessionConfigOption>>,
1102 #[serde_as(deserialize_as = "DefaultOnError")]
1108 #[schemars(extend("x-deserialize-default-on-error" = true))]
1109 #[serde(default)]
1110 #[serde(rename = "_meta")]
1111 pub meta: Option<Meta>,
1112}
1113
1114impl NewSessionResponse {
1115 #[must_use]
1117 pub fn new(session_id: impl Into<SessionId>) -> Self {
1118 Self {
1119 session_id: session_id.into(),
1120 modes: None,
1121 config_options: None,
1122 meta: None,
1123 }
1124 }
1125
1126 #[must_use]
1130 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1131 self.modes = modes.into_option();
1132 self
1133 }
1134
1135 #[must_use]
1137 pub fn config_options(
1138 mut self,
1139 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1140 ) -> Self {
1141 self.config_options = config_options.into_option();
1142 self
1143 }
1144
1145 #[must_use]
1151 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1152 self.meta = meta.into_option();
1153 self
1154 }
1155}
1156
1157#[serde_as]
1165#[skip_serializing_none]
1166#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1167#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1168#[serde(rename_all = "camelCase")]
1169#[non_exhaustive]
1170pub struct LoadSessionRequest {
1171 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1173 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1174 pub mcp_servers: Vec<McpServer>,
1175 pub cwd: PathBuf,
1177 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1184 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1185 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1186 pub additional_directories: Vec<PathBuf>,
1187 pub session_id: SessionId,
1189 #[serde_as(deserialize_as = "DefaultOnError")]
1195 #[schemars(extend("x-deserialize-default-on-error" = true))]
1196 #[serde(default)]
1197 #[serde(rename = "_meta")]
1198 pub meta: Option<Meta>,
1199}
1200
1201impl LoadSessionRequest {
1202 #[must_use]
1204 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1205 Self {
1206 mcp_servers: vec![],
1207 cwd: cwd.into(),
1208 additional_directories: vec![],
1209 session_id: session_id.into(),
1210 meta: None,
1211 }
1212 }
1213
1214 #[must_use]
1216 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1217 self.additional_directories = additional_directories;
1218 self
1219 }
1220
1221 #[must_use]
1223 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1224 self.mcp_servers = mcp_servers;
1225 self
1226 }
1227
1228 #[must_use]
1234 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1235 self.meta = meta.into_option();
1236 self
1237 }
1238}
1239
1240#[serde_as]
1242#[skip_serializing_none]
1243#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1244#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1245#[serde(rename_all = "camelCase")]
1246#[non_exhaustive]
1247pub struct LoadSessionResponse {
1248 #[serde_as(deserialize_as = "DefaultOnError")]
1252 #[schemars(extend("x-deserialize-default-on-error" = true))]
1253 #[serde(default)]
1254 pub modes: Option<SessionModeState>,
1255 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1257 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1258 #[serde(default)]
1259 pub config_options: Option<Vec<SessionConfigOption>>,
1260 #[serde_as(deserialize_as = "DefaultOnError")]
1266 #[schemars(extend("x-deserialize-default-on-error" = true))]
1267 #[serde(default)]
1268 #[serde(rename = "_meta")]
1269 pub meta: Option<Meta>,
1270}
1271
1272impl LoadSessionResponse {
1273 #[must_use]
1275 pub fn new() -> Self {
1276 Self::default()
1277 }
1278
1279 #[must_use]
1283 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1284 self.modes = modes.into_option();
1285 self
1286 }
1287
1288 #[must_use]
1290 pub fn config_options(
1291 mut self,
1292 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1293 ) -> Self {
1294 self.config_options = config_options.into_option();
1295 self
1296 }
1297
1298 #[must_use]
1304 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1305 self.meta = meta.into_option();
1306 self
1307 }
1308}
1309
1310#[cfg(feature = "unstable_session_fork")]
1323#[serde_as]
1324#[skip_serializing_none]
1325#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1326#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1327#[serde(rename_all = "camelCase")]
1328#[non_exhaustive]
1329pub struct ForkSessionRequest {
1330 pub session_id: SessionId,
1332 pub cwd: PathBuf,
1334 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1340 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1341 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1342 pub additional_directories: Vec<PathBuf>,
1343 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1345 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1346 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1347 pub mcp_servers: Vec<McpServer>,
1348 #[serde_as(deserialize_as = "DefaultOnError")]
1354 #[schemars(extend("x-deserialize-default-on-error" = true))]
1355 #[serde(default)]
1356 #[serde(rename = "_meta")]
1357 pub meta: Option<Meta>,
1358}
1359
1360#[cfg(feature = "unstable_session_fork")]
1361impl ForkSessionRequest {
1362 #[must_use]
1364 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1365 Self {
1366 session_id: session_id.into(),
1367 cwd: cwd.into(),
1368 additional_directories: vec![],
1369 mcp_servers: vec![],
1370 meta: None,
1371 }
1372 }
1373
1374 #[must_use]
1376 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1377 self.additional_directories = additional_directories;
1378 self
1379 }
1380
1381 #[must_use]
1383 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1384 self.mcp_servers = mcp_servers;
1385 self
1386 }
1387
1388 #[must_use]
1394 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1395 self.meta = meta.into_option();
1396 self
1397 }
1398}
1399
1400#[cfg(feature = "unstable_session_fork")]
1406#[serde_as]
1407#[skip_serializing_none]
1408#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1409#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1410#[serde(rename_all = "camelCase")]
1411#[non_exhaustive]
1412pub struct ForkSessionResponse {
1413 pub session_id: SessionId,
1415 #[serde_as(deserialize_as = "DefaultOnError")]
1419 #[schemars(extend("x-deserialize-default-on-error" = true))]
1420 #[serde(default)]
1421 pub modes: Option<SessionModeState>,
1422 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1424 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1425 #[serde(default)]
1426 pub config_options: Option<Vec<SessionConfigOption>>,
1427 #[serde_as(deserialize_as = "DefaultOnError")]
1433 #[schemars(extend("x-deserialize-default-on-error" = true))]
1434 #[serde(default)]
1435 #[serde(rename = "_meta")]
1436 pub meta: Option<Meta>,
1437}
1438
1439#[cfg(feature = "unstable_session_fork")]
1440impl ForkSessionResponse {
1441 #[must_use]
1443 pub fn new(session_id: impl Into<SessionId>) -> Self {
1444 Self {
1445 session_id: session_id.into(),
1446 modes: None,
1447 config_options: None,
1448 meta: None,
1449 }
1450 }
1451
1452 #[must_use]
1456 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1457 self.modes = modes.into_option();
1458 self
1459 }
1460
1461 #[must_use]
1463 pub fn config_options(
1464 mut self,
1465 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1466 ) -> Self {
1467 self.config_options = config_options.into_option();
1468 self
1469 }
1470
1471 #[must_use]
1477 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1478 self.meta = meta.into_option();
1479 self
1480 }
1481}
1482
1483#[serde_as]
1492#[skip_serializing_none]
1493#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1494#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1495#[serde(rename_all = "camelCase")]
1496#[non_exhaustive]
1497pub struct ResumeSessionRequest {
1498 pub session_id: SessionId,
1500 pub cwd: PathBuf,
1502 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1509 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1510 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1511 pub additional_directories: Vec<PathBuf>,
1512 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1514 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1515 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1516 pub mcp_servers: Vec<McpServer>,
1517 #[serde_as(deserialize_as = "DefaultOnError")]
1523 #[schemars(extend("x-deserialize-default-on-error" = true))]
1524 #[serde(default)]
1525 #[serde(rename = "_meta")]
1526 pub meta: Option<Meta>,
1527}
1528
1529impl ResumeSessionRequest {
1530 #[must_use]
1532 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1533 Self {
1534 session_id: session_id.into(),
1535 cwd: cwd.into(),
1536 additional_directories: vec![],
1537 mcp_servers: vec![],
1538 meta: None,
1539 }
1540 }
1541
1542 #[must_use]
1544 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1545 self.additional_directories = additional_directories;
1546 self
1547 }
1548
1549 #[must_use]
1551 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1552 self.mcp_servers = mcp_servers;
1553 self
1554 }
1555
1556 #[must_use]
1562 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1563 self.meta = meta.into_option();
1564 self
1565 }
1566}
1567
1568#[serde_as]
1570#[skip_serializing_none]
1571#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1572#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1573#[serde(rename_all = "camelCase")]
1574#[non_exhaustive]
1575pub struct ResumeSessionResponse {
1576 #[serde_as(deserialize_as = "DefaultOnError")]
1580 #[schemars(extend("x-deserialize-default-on-error" = true))]
1581 #[serde(default)]
1582 pub modes: Option<SessionModeState>,
1583 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1585 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1586 #[serde(default)]
1587 pub config_options: Option<Vec<SessionConfigOption>>,
1588 #[serde_as(deserialize_as = "DefaultOnError")]
1594 #[schemars(extend("x-deserialize-default-on-error" = true))]
1595 #[serde(default)]
1596 #[serde(rename = "_meta")]
1597 pub meta: Option<Meta>,
1598}
1599
1600impl ResumeSessionResponse {
1601 #[must_use]
1603 pub fn new() -> Self {
1604 Self::default()
1605 }
1606
1607 #[must_use]
1611 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1612 self.modes = modes.into_option();
1613 self
1614 }
1615
1616 #[must_use]
1618 pub fn config_options(
1619 mut self,
1620 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1621 ) -> Self {
1622 self.config_options = config_options.into_option();
1623 self
1624 }
1625
1626 #[must_use]
1632 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1633 self.meta = meta.into_option();
1634 self
1635 }
1636}
1637
1638#[serde_as]
1648#[skip_serializing_none]
1649#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1650#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1651#[serde(rename_all = "camelCase")]
1652#[non_exhaustive]
1653pub struct CloseSessionRequest {
1654 pub session_id: SessionId,
1656 #[serde_as(deserialize_as = "DefaultOnError")]
1662 #[schemars(extend("x-deserialize-default-on-error" = true))]
1663 #[serde(default)]
1664 #[serde(rename = "_meta")]
1665 pub meta: Option<Meta>,
1666}
1667
1668impl CloseSessionRequest {
1669 #[must_use]
1671 pub fn new(session_id: impl Into<SessionId>) -> Self {
1672 Self {
1673 session_id: session_id.into(),
1674 meta: None,
1675 }
1676 }
1677
1678 #[must_use]
1684 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1685 self.meta = meta.into_option();
1686 self
1687 }
1688}
1689
1690#[serde_as]
1692#[skip_serializing_none]
1693#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1694#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1695#[serde(rename_all = "camelCase")]
1696#[non_exhaustive]
1697pub struct CloseSessionResponse {
1698 #[serde_as(deserialize_as = "DefaultOnError")]
1704 #[schemars(extend("x-deserialize-default-on-error" = true))]
1705 #[serde(default)]
1706 #[serde(rename = "_meta")]
1707 pub meta: Option<Meta>,
1708}
1709
1710impl CloseSessionResponse {
1711 #[must_use]
1713 pub fn new() -> Self {
1714 Self::default()
1715 }
1716
1717 #[must_use]
1723 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1724 self.meta = meta.into_option();
1725 self
1726 }
1727}
1728
1729#[serde_as]
1735#[skip_serializing_none]
1736#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1737#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1738#[serde(rename_all = "camelCase")]
1739#[non_exhaustive]
1740pub struct ListSessionsRequest {
1741 #[serde_as(deserialize_as = "DefaultOnError")]
1743 #[schemars(extend("x-deserialize-default-on-error" = true))]
1744 #[serde(default)]
1745 pub cwd: Option<PathBuf>,
1746 #[serde_as(deserialize_as = "DefaultOnError")]
1748 #[schemars(extend("x-deserialize-default-on-error" = true))]
1749 #[serde(default)]
1750 pub cursor: Option<String>,
1751 #[serde_as(deserialize_as = "DefaultOnError")]
1757 #[schemars(extend("x-deserialize-default-on-error" = true))]
1758 #[serde(default)]
1759 #[serde(rename = "_meta")]
1760 pub meta: Option<Meta>,
1761}
1762
1763impl ListSessionsRequest {
1764 #[must_use]
1766 pub fn new() -> Self {
1767 Self::default()
1768 }
1769
1770 #[must_use]
1772 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1773 self.cwd = cwd.into_option();
1774 self
1775 }
1776
1777 #[must_use]
1779 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1780 self.cursor = cursor.into_option();
1781 self
1782 }
1783
1784 #[must_use]
1790 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1791 self.meta = meta.into_option();
1792 self
1793 }
1794}
1795
1796#[serde_as]
1798#[skip_serializing_none]
1799#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1800#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1801#[serde(rename_all = "camelCase")]
1802#[non_exhaustive]
1803pub struct ListSessionsResponse {
1804 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1806 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1807 pub sessions: Vec<SessionInfo>,
1808 #[serde_as(deserialize_as = "DefaultOnError")]
1811 #[schemars(extend("x-deserialize-default-on-error" = true))]
1812 #[serde(default)]
1813 pub next_cursor: Option<String>,
1814 #[serde_as(deserialize_as = "DefaultOnError")]
1820 #[schemars(extend("x-deserialize-default-on-error" = true))]
1821 #[serde(default)]
1822 #[serde(rename = "_meta")]
1823 pub meta: Option<Meta>,
1824}
1825
1826impl ListSessionsResponse {
1827 #[must_use]
1829 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1830 Self {
1831 sessions,
1832 next_cursor: None,
1833 meta: None,
1834 }
1835 }
1836
1837 #[must_use]
1839 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1840 self.next_cursor = next_cursor.into_option();
1841 self
1842 }
1843
1844 #[must_use]
1850 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1851 self.meta = meta.into_option();
1852 self
1853 }
1854}
1855
1856#[serde_as]
1862#[skip_serializing_none]
1863#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1864#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1865#[serde(rename_all = "camelCase")]
1866#[non_exhaustive]
1867pub struct DeleteSessionRequest {
1868 pub session_id: SessionId,
1870 #[serde_as(deserialize_as = "DefaultOnError")]
1876 #[schemars(extend("x-deserialize-default-on-error" = true))]
1877 #[serde(default)]
1878 #[serde(rename = "_meta")]
1879 pub meta: Option<Meta>,
1880}
1881
1882impl DeleteSessionRequest {
1883 #[must_use]
1885 pub fn new(session_id: impl Into<SessionId>) -> Self {
1886 Self {
1887 session_id: session_id.into(),
1888 meta: None,
1889 }
1890 }
1891
1892 #[must_use]
1898 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1899 self.meta = meta.into_option();
1900 self
1901 }
1902}
1903
1904#[serde_as]
1906#[skip_serializing_none]
1907#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1908#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1909#[serde(rename_all = "camelCase")]
1910#[non_exhaustive]
1911pub struct DeleteSessionResponse {
1912 #[serde_as(deserialize_as = "DefaultOnError")]
1918 #[schemars(extend("x-deserialize-default-on-error" = true))]
1919 #[serde(default)]
1920 #[serde(rename = "_meta")]
1921 pub meta: Option<Meta>,
1922}
1923
1924impl DeleteSessionResponse {
1925 #[must_use]
1927 pub fn new() -> Self {
1928 Self::default()
1929 }
1930
1931 #[must_use]
1937 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1938 self.meta = meta.into_option();
1939 self
1940 }
1941}
1942
1943#[serde_as]
1945#[skip_serializing_none]
1946#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1947#[serde(rename_all = "camelCase")]
1948#[non_exhaustive]
1949pub struct SessionInfo {
1950 pub session_id: SessionId,
1952 pub cwd: PathBuf,
1954 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1960 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1961 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1962 pub additional_directories: Vec<PathBuf>,
1963
1964 #[serde_as(deserialize_as = "DefaultOnError")]
1966 #[schemars(extend("x-deserialize-default-on-error" = true))]
1967 #[serde(default)]
1968 pub title: Option<String>,
1969 #[serde_as(deserialize_as = "DefaultOnError")]
1971 #[schemars(extend("x-deserialize-default-on-error" = true))]
1972 #[serde(default)]
1973 pub updated_at: Option<String>,
1974 #[serde_as(deserialize_as = "DefaultOnError")]
1980 #[schemars(extend("x-deserialize-default-on-error" = true))]
1981 #[serde(default)]
1982 #[serde(rename = "_meta")]
1983 pub meta: Option<Meta>,
1984}
1985
1986impl SessionInfo {
1987 #[must_use]
1989 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1990 Self {
1991 session_id: session_id.into(),
1992 cwd: cwd.into(),
1993 additional_directories: vec![],
1994 title: None,
1995 updated_at: None,
1996 meta: None,
1997 }
1998 }
1999
2000 #[must_use]
2002 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
2003 self.additional_directories = additional_directories;
2004 self
2005 }
2006
2007 #[must_use]
2009 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
2010 self.title = title.into_option();
2011 self
2012 }
2013
2014 #[must_use]
2016 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
2017 self.updated_at = updated_at.into_option();
2018 self
2019 }
2020
2021 #[must_use]
2027 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2028 self.meta = meta.into_option();
2029 self
2030 }
2031}
2032
2033#[serde_as]
2037#[skip_serializing_none]
2038#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2039#[serde(rename_all = "camelCase")]
2040#[non_exhaustive]
2041pub struct SessionModeState {
2042 pub current_mode_id: SessionModeId,
2044 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2046 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2047 pub available_modes: Vec<SessionMode>,
2048 #[serde_as(deserialize_as = "DefaultOnError")]
2054 #[schemars(extend("x-deserialize-default-on-error" = true))]
2055 #[serde(default)]
2056 #[serde(rename = "_meta")]
2057 pub meta: Option<Meta>,
2058}
2059
2060impl SessionModeState {
2061 #[must_use]
2063 pub fn new(
2064 current_mode_id: impl Into<SessionModeId>,
2065 available_modes: Vec<SessionMode>,
2066 ) -> Self {
2067 Self {
2068 current_mode_id: current_mode_id.into(),
2069 available_modes,
2070 meta: None,
2071 }
2072 }
2073
2074 #[must_use]
2080 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2081 self.meta = meta.into_option();
2082 self
2083 }
2084}
2085
2086#[serde_as]
2090#[skip_serializing_none]
2091#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2092#[serde(rename_all = "camelCase")]
2093#[non_exhaustive]
2094pub struct SessionMode {
2095 pub id: SessionModeId,
2097 pub name: String,
2099 #[serde_as(deserialize_as = "DefaultOnError")]
2101 #[schemars(extend("x-deserialize-default-on-error" = true))]
2102 #[serde(default)]
2103 pub description: Option<String>,
2104 #[serde_as(deserialize_as = "DefaultOnError")]
2110 #[schemars(extend("x-deserialize-default-on-error" = true))]
2111 #[serde(default)]
2112 #[serde(rename = "_meta")]
2113 pub meta: Option<Meta>,
2114}
2115
2116impl SessionMode {
2117 #[must_use]
2119 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
2120 Self {
2121 id: id.into(),
2122 name: name.into(),
2123 description: None,
2124 meta: None,
2125 }
2126 }
2127
2128 #[must_use]
2130 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2131 self.description = description.into_option();
2132 self
2133 }
2134
2135 #[must_use]
2141 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2142 self.meta = meta.into_option();
2143 self
2144 }
2145}
2146
2147#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2149#[serde(transparent)]
2150#[from(Arc<str>, String, &'static str)]
2151#[non_exhaustive]
2152pub struct SessionModeId(pub Arc<str>);
2153
2154impl SessionModeId {
2155 #[must_use]
2157 pub fn new(id: impl Into<Arc<str>>) -> Self {
2158 Self(id.into())
2159 }
2160}
2161
2162#[serde_as]
2164#[skip_serializing_none]
2165#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2166#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2167#[serde(rename_all = "camelCase")]
2168#[non_exhaustive]
2169pub struct SetSessionModeRequest {
2170 pub session_id: SessionId,
2172 pub mode_id: SessionModeId,
2174 #[serde_as(deserialize_as = "DefaultOnError")]
2180 #[schemars(extend("x-deserialize-default-on-error" = true))]
2181 #[serde(default)]
2182 #[serde(rename = "_meta")]
2183 pub meta: Option<Meta>,
2184}
2185
2186impl SetSessionModeRequest {
2187 #[must_use]
2189 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2190 Self {
2191 session_id: session_id.into(),
2192 mode_id: mode_id.into(),
2193 meta: None,
2194 }
2195 }
2196
2197 #[must_use]
2199 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2200 self.meta = meta.into_option();
2201 self
2202 }
2203}
2204
2205#[serde_as]
2207#[skip_serializing_none]
2208#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2209#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
2210#[serde(rename_all = "camelCase")]
2211#[non_exhaustive]
2212pub struct SetSessionModeResponse {
2213 #[serde_as(deserialize_as = "DefaultOnError")]
2219 #[schemars(extend("x-deserialize-default-on-error" = true))]
2220 #[serde(default)]
2221 #[serde(rename = "_meta")]
2222 pub meta: Option<Meta>,
2223}
2224
2225impl SetSessionModeResponse {
2226 #[must_use]
2228 pub fn new() -> Self {
2229 Self::default()
2230 }
2231
2232 #[must_use]
2238 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2239 self.meta = meta.into_option();
2240 self
2241 }
2242}
2243
2244#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2248#[serde(transparent)]
2249#[from(Arc<str>, String, &'static str)]
2250#[non_exhaustive]
2251pub struct SessionConfigId(pub Arc<str>);
2252
2253impl SessionConfigId {
2254 #[must_use]
2256 pub fn new(id: impl Into<Arc<str>>) -> Self {
2257 Self(id.into())
2258 }
2259}
2260
2261#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2263#[serde(transparent)]
2264#[from(Arc<str>, String, &'static str)]
2265#[non_exhaustive]
2266pub struct SessionConfigValueId(pub Arc<str>);
2267
2268impl SessionConfigValueId {
2269 #[must_use]
2271 pub fn new(id: impl Into<Arc<str>>) -> Self {
2272 Self(id.into())
2273 }
2274}
2275
2276#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
2278#[serde(transparent)]
2279#[from(Arc<str>, String, &'static str)]
2280#[non_exhaustive]
2281pub struct SessionConfigGroupId(pub Arc<str>);
2282
2283impl SessionConfigGroupId {
2284 #[must_use]
2286 pub fn new(id: impl Into<Arc<str>>) -> Self {
2287 Self(id.into())
2288 }
2289}
2290
2291#[serde_as]
2293#[skip_serializing_none]
2294#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2295#[serde(rename_all = "camelCase")]
2296#[non_exhaustive]
2297pub struct SessionConfigSelectOption {
2298 pub value: SessionConfigValueId,
2300 pub name: String,
2302 #[serde_as(deserialize_as = "DefaultOnError")]
2304 #[schemars(extend("x-deserialize-default-on-error" = true))]
2305 #[serde(default)]
2306 pub description: Option<String>,
2307 #[serde_as(deserialize_as = "DefaultOnError")]
2313 #[schemars(extend("x-deserialize-default-on-error" = true))]
2314 #[serde(default)]
2315 #[serde(rename = "_meta")]
2316 pub meta: Option<Meta>,
2317}
2318
2319impl SessionConfigSelectOption {
2320 #[must_use]
2322 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2323 Self {
2324 value: value.into(),
2325 name: name.into(),
2326 description: None,
2327 meta: None,
2328 }
2329 }
2330
2331 #[must_use]
2333 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2334 self.description = description.into_option();
2335 self
2336 }
2337
2338 #[must_use]
2344 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2345 self.meta = meta.into_option();
2346 self
2347 }
2348}
2349
2350#[serde_as]
2352#[skip_serializing_none]
2353#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2354#[serde(rename_all = "camelCase")]
2355#[non_exhaustive]
2356pub struct SessionConfigSelectGroup {
2357 pub group: SessionConfigGroupId,
2359 pub name: String,
2361 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2363 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2364 pub options: Vec<SessionConfigSelectOption>,
2365 #[serde_as(deserialize_as = "DefaultOnError")]
2371 #[schemars(extend("x-deserialize-default-on-error" = true))]
2372 #[serde(default)]
2373 #[serde(rename = "_meta")]
2374 pub meta: Option<Meta>,
2375}
2376
2377impl SessionConfigSelectGroup {
2378 #[must_use]
2380 pub fn new(
2381 group: impl Into<SessionConfigGroupId>,
2382 name: impl Into<String>,
2383 options: Vec<SessionConfigSelectOption>,
2384 ) -> Self {
2385 Self {
2386 group: group.into(),
2387 name: name.into(),
2388 options,
2389 meta: None,
2390 }
2391 }
2392
2393 #[must_use]
2399 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2400 self.meta = meta.into_option();
2401 self
2402 }
2403}
2404
2405#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2407#[serde(untagged)]
2408#[non_exhaustive]
2409pub enum SessionConfigSelectOptions {
2410 Ungrouped(Vec<SessionConfigSelectOption>),
2412 Grouped(Vec<SessionConfigSelectGroup>),
2414}
2415
2416impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2417 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2418 SessionConfigSelectOptions::Ungrouped(options)
2419 }
2420}
2421
2422impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2423 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2424 SessionConfigSelectOptions::Grouped(groups)
2425 }
2426}
2427
2428#[skip_serializing_none]
2430#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2431#[serde(rename_all = "camelCase")]
2432#[non_exhaustive]
2433pub struct SessionConfigSelect {
2434 pub current_value: SessionConfigValueId,
2436 pub options: SessionConfigSelectOptions,
2438}
2439
2440impl SessionConfigSelect {
2441 #[must_use]
2443 pub fn new(
2444 current_value: impl Into<SessionConfigValueId>,
2445 options: impl Into<SessionConfigSelectOptions>,
2446 ) -> Self {
2447 Self {
2448 current_value: current_value.into(),
2449 options: options.into(),
2450 }
2451 }
2452}
2453
2454#[cfg(feature = "unstable_boolean_config")]
2460#[skip_serializing_none]
2461#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2462#[serde(rename_all = "camelCase")]
2463#[non_exhaustive]
2464pub struct SessionConfigBoolean {
2465 pub current_value: bool,
2467}
2468
2469#[cfg(feature = "unstable_boolean_config")]
2470impl SessionConfigBoolean {
2471 #[must_use]
2473 pub fn new(current_value: bool) -> Self {
2474 Self { current_value }
2475 }
2476}
2477
2478#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2488#[serde(rename_all = "snake_case")]
2489#[non_exhaustive]
2490pub enum SessionConfigOptionCategory {
2491 Mode,
2493 Model,
2495 ModelConfig,
2497 ThoughtLevel,
2499 #[serde(untagged)]
2501 Other(String),
2502}
2503
2504#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2506#[serde(tag = "type", rename_all = "snake_case")]
2507#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2508#[non_exhaustive]
2509pub enum SessionConfigKind {
2510 Select(SessionConfigSelect),
2512 #[cfg(feature = "unstable_boolean_config")]
2518 Boolean(SessionConfigBoolean),
2519}
2520
2521#[serde_as]
2523#[skip_serializing_none]
2524#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2525#[serde(rename_all = "camelCase")]
2526#[non_exhaustive]
2527pub struct SessionConfigOption {
2528 pub id: SessionConfigId,
2530 pub name: String,
2532 #[serde_as(deserialize_as = "DefaultOnError")]
2534 #[schemars(extend("x-deserialize-default-on-error" = true))]
2535 #[serde(default)]
2536 pub description: Option<String>,
2537 #[serde_as(deserialize_as = "DefaultOnError")]
2539 #[schemars(extend("x-deserialize-default-on-error" = true))]
2540 #[serde(default)]
2541 pub category: Option<SessionConfigOptionCategory>,
2542 #[serde(flatten)]
2544 pub kind: SessionConfigKind,
2545 #[serde_as(deserialize_as = "DefaultOnError")]
2551 #[schemars(extend("x-deserialize-default-on-error" = true))]
2552 #[serde(default)]
2553 #[serde(rename = "_meta")]
2554 pub meta: Option<Meta>,
2555}
2556
2557impl SessionConfigOption {
2558 #[must_use]
2560 pub fn new(
2561 id: impl Into<SessionConfigId>,
2562 name: impl Into<String>,
2563 kind: SessionConfigKind,
2564 ) -> Self {
2565 Self {
2566 id: id.into(),
2567 name: name.into(),
2568 description: None,
2569 category: None,
2570 kind,
2571 meta: None,
2572 }
2573 }
2574
2575 #[must_use]
2577 pub fn select(
2578 id: impl Into<SessionConfigId>,
2579 name: impl Into<String>,
2580 current_value: impl Into<SessionConfigValueId>,
2581 options: impl Into<SessionConfigSelectOptions>,
2582 ) -> Self {
2583 Self::new(
2584 id,
2585 name,
2586 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2587 )
2588 }
2589
2590 #[cfg(feature = "unstable_boolean_config")]
2594 #[must_use]
2595 pub fn boolean(
2596 id: impl Into<SessionConfigId>,
2597 name: impl Into<String>,
2598 current_value: bool,
2599 ) -> Self {
2600 Self::new(
2601 id,
2602 name,
2603 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2604 )
2605 }
2606
2607 #[must_use]
2609 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2610 self.description = description.into_option();
2611 self
2612 }
2613
2614 #[must_use]
2616 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2617 self.category = category.into_option();
2618 self
2619 }
2620
2621 #[must_use]
2627 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2628 self.meta = meta.into_option();
2629 self
2630 }
2631}
2632
2633#[cfg(feature = "unstable_boolean_config")]
2648#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2649#[serde(tag = "type", rename_all = "snake_case")]
2650#[non_exhaustive]
2651pub enum SessionConfigOptionValue {
2652 Boolean {
2654 value: bool,
2656 },
2657 #[serde(untagged)]
2663 ValueId {
2664 value: SessionConfigValueId,
2666 },
2667}
2668
2669#[cfg(feature = "unstable_boolean_config")]
2670impl SessionConfigOptionValue {
2671 #[must_use]
2673 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2674 Self::ValueId { value: id.into() }
2675 }
2676
2677 #[must_use]
2679 pub fn boolean(val: bool) -> Self {
2680 Self::Boolean { value: val }
2681 }
2682
2683 #[must_use]
2686 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2687 match self {
2688 Self::ValueId { value } => Some(value),
2689 _ => None,
2690 }
2691 }
2692
2693 #[must_use]
2695 pub fn as_bool(&self) -> Option<bool> {
2696 match self {
2697 Self::Boolean { value } => Some(*value),
2698 _ => None,
2699 }
2700 }
2701}
2702
2703#[cfg(feature = "unstable_boolean_config")]
2704impl From<SessionConfigValueId> for SessionConfigOptionValue {
2705 fn from(value: SessionConfigValueId) -> Self {
2706 Self::ValueId { value }
2707 }
2708}
2709
2710#[cfg(feature = "unstable_boolean_config")]
2711impl From<bool> for SessionConfigOptionValue {
2712 fn from(value: bool) -> Self {
2713 Self::Boolean { value }
2714 }
2715}
2716
2717#[cfg(feature = "unstable_boolean_config")]
2718impl From<&str> for SessionConfigOptionValue {
2719 fn from(value: &str) -> Self {
2720 Self::ValueId {
2721 value: SessionConfigValueId::new(value),
2722 }
2723 }
2724}
2725
2726#[serde_as]
2728#[skip_serializing_none]
2729#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2730#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2731#[serde(rename_all = "camelCase")]
2732#[non_exhaustive]
2733pub struct SetSessionConfigOptionRequest {
2734 pub session_id: SessionId,
2736 pub config_id: SessionConfigId,
2738 #[cfg(feature = "unstable_boolean_config")]
2743 #[serde(flatten)]
2744 pub value: SessionConfigOptionValue,
2745 #[cfg(not(feature = "unstable_boolean_config"))]
2747 pub value: SessionConfigValueId,
2748 #[serde_as(deserialize_as = "DefaultOnError")]
2754 #[schemars(extend("x-deserialize-default-on-error" = true))]
2755 #[serde(default)]
2756 #[serde(rename = "_meta")]
2757 pub meta: Option<Meta>,
2758}
2759
2760impl SetSessionConfigOptionRequest {
2761 #[cfg(feature = "unstable_boolean_config")]
2763 #[must_use]
2764 pub fn new(
2765 session_id: impl Into<SessionId>,
2766 config_id: impl Into<SessionConfigId>,
2767 value: impl Into<SessionConfigOptionValue>,
2768 ) -> Self {
2769 Self {
2770 session_id: session_id.into(),
2771 config_id: config_id.into(),
2772 value: value.into(),
2773 meta: None,
2774 }
2775 }
2776
2777 #[cfg(not(feature = "unstable_boolean_config"))]
2780 #[must_use]
2781 pub fn new(
2782 session_id: impl Into<SessionId>,
2783 config_id: impl Into<SessionConfigId>,
2784 value: impl Into<SessionConfigValueId>,
2785 ) -> Self {
2786 Self {
2787 session_id: session_id.into(),
2788 config_id: config_id.into(),
2789 value: value.into(),
2790 meta: None,
2791 }
2792 }
2793
2794 #[must_use]
2800 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2801 self.meta = meta.into_option();
2802 self
2803 }
2804}
2805
2806#[serde_as]
2808#[skip_serializing_none]
2809#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2810#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2811#[serde(rename_all = "camelCase")]
2812#[non_exhaustive]
2813pub struct SetSessionConfigOptionResponse {
2814 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2816 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2817 pub config_options: Vec<SessionConfigOption>,
2818 #[serde_as(deserialize_as = "DefaultOnError")]
2824 #[schemars(extend("x-deserialize-default-on-error" = true))]
2825 #[serde(default)]
2826 #[serde(rename = "_meta")]
2827 pub meta: Option<Meta>,
2828}
2829
2830impl SetSessionConfigOptionResponse {
2831 #[must_use]
2833 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2834 Self {
2835 config_options,
2836 meta: None,
2837 }
2838 }
2839
2840 #[must_use]
2846 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2847 self.meta = meta.into_option();
2848 self
2849 }
2850}
2851
2852#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2861#[serde(tag = "type", rename_all = "snake_case")]
2862#[non_exhaustive]
2863pub enum McpServer {
2864 Http(McpServerHttp),
2868 Sse(McpServerSse),
2872 #[cfg(feature = "unstable_mcp_over_acp")]
2881 Acp(McpServerAcp),
2882 #[serde(untagged)]
2886 Stdio(McpServerStdio),
2887}
2888
2889#[serde_as]
2891#[skip_serializing_none]
2892#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2893#[serde(rename_all = "camelCase")]
2894#[non_exhaustive]
2895pub struct McpServerHttp {
2896 pub name: String,
2898 pub url: String,
2900 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2902 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2903 pub headers: Vec<HttpHeader>,
2904 #[serde_as(deserialize_as = "DefaultOnError")]
2910 #[schemars(extend("x-deserialize-default-on-error" = true))]
2911 #[serde(default)]
2912 #[serde(rename = "_meta")]
2913 pub meta: Option<Meta>,
2914}
2915
2916impl McpServerHttp {
2917 #[must_use]
2919 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2920 Self {
2921 name: name.into(),
2922 url: url.into(),
2923 headers: Vec::new(),
2924 meta: None,
2925 }
2926 }
2927
2928 #[must_use]
2930 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2931 self.headers = headers;
2932 self
2933 }
2934
2935 #[must_use]
2941 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2942 self.meta = meta.into_option();
2943 self
2944 }
2945}
2946
2947#[serde_as]
2949#[skip_serializing_none]
2950#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2951#[serde(rename_all = "camelCase")]
2952#[non_exhaustive]
2953pub struct McpServerSse {
2954 pub name: String,
2956 pub url: String,
2958 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2960 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2961 pub headers: Vec<HttpHeader>,
2962 #[serde_as(deserialize_as = "DefaultOnError")]
2968 #[schemars(extend("x-deserialize-default-on-error" = true))]
2969 #[serde(default)]
2970 #[serde(rename = "_meta")]
2971 pub meta: Option<Meta>,
2972}
2973
2974impl McpServerSse {
2975 #[must_use]
2977 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2978 Self {
2979 name: name.into(),
2980 url: url.into(),
2981 headers: Vec::new(),
2982 meta: None,
2983 }
2984 }
2985
2986 #[must_use]
2988 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2989 self.headers = headers;
2990 self
2991 }
2992
2993 #[must_use]
2999 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3000 self.meta = meta.into_option();
3001 self
3002 }
3003}
3004
3005#[cfg(feature = "unstable_mcp_over_acp")]
3015#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
3016#[serde(transparent)]
3017#[from(Arc<str>, String, &'static str)]
3018#[non_exhaustive]
3019pub struct McpServerAcpId(pub Arc<str>);
3020
3021#[cfg(feature = "unstable_mcp_over_acp")]
3022impl McpServerAcpId {
3023 #[must_use]
3025 pub fn new(id: impl Into<Arc<str>>) -> Self {
3026 Self(id.into())
3027 }
3028}
3029
3030#[serde_as]
3039#[skip_serializing_none]
3040#[cfg(feature = "unstable_mcp_over_acp")]
3041#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3042#[serde(rename_all = "camelCase")]
3043#[non_exhaustive]
3044pub struct McpServerAcp {
3045 pub name: String,
3047 pub id: McpServerAcpId,
3052 #[serde_as(deserialize_as = "DefaultOnError")]
3058 #[schemars(extend("x-deserialize-default-on-error" = true))]
3059 #[serde(default)]
3060 #[serde(rename = "_meta")]
3061 pub meta: Option<Meta>,
3062}
3063
3064#[cfg(feature = "unstable_mcp_over_acp")]
3065impl McpServerAcp {
3066 #[must_use]
3068 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
3069 Self {
3070 name: name.into(),
3071 id: id.into(),
3072 meta: None,
3073 }
3074 }
3075
3076 #[must_use]
3082 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3083 self.meta = meta.into_option();
3084 self
3085 }
3086}
3087
3088#[serde_as]
3090#[skip_serializing_none]
3091#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3092#[serde(rename_all = "camelCase")]
3093#[non_exhaustive]
3094pub struct McpServerStdio {
3095 pub name: String,
3097 pub command: PathBuf,
3099 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3101 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3102 pub args: Vec<String>,
3103 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3105 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3106 pub env: Vec<EnvVariable>,
3107 #[serde_as(deserialize_as = "DefaultOnError")]
3113 #[schemars(extend("x-deserialize-default-on-error" = true))]
3114 #[serde(default)]
3115 #[serde(rename = "_meta")]
3116 pub meta: Option<Meta>,
3117}
3118
3119impl McpServerStdio {
3120 #[must_use]
3122 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
3123 Self {
3124 name: name.into(),
3125 command: command.into(),
3126 args: Vec::new(),
3127 env: Vec::new(),
3128 meta: None,
3129 }
3130 }
3131
3132 #[must_use]
3134 pub fn args(mut self, args: Vec<String>) -> Self {
3135 self.args = args;
3136 self
3137 }
3138
3139 #[must_use]
3141 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
3142 self.env = env;
3143 self
3144 }
3145
3146 #[must_use]
3152 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3153 self.meta = meta.into_option();
3154 self
3155 }
3156}
3157
3158#[serde_as]
3160#[skip_serializing_none]
3161#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3162#[serde(rename_all = "camelCase")]
3163#[non_exhaustive]
3164pub struct EnvVariable {
3165 pub name: String,
3167 pub value: String,
3169 #[serde_as(deserialize_as = "DefaultOnError")]
3175 #[schemars(extend("x-deserialize-default-on-error" = true))]
3176 #[serde(default)]
3177 #[serde(rename = "_meta")]
3178 pub meta: Option<Meta>,
3179}
3180
3181impl EnvVariable {
3182 #[must_use]
3184 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3185 Self {
3186 name: name.into(),
3187 value: value.into(),
3188 meta: None,
3189 }
3190 }
3191
3192 #[must_use]
3198 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3199 self.meta = meta.into_option();
3200 self
3201 }
3202}
3203
3204#[serde_as]
3206#[skip_serializing_none]
3207#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3208#[serde(rename_all = "camelCase")]
3209#[non_exhaustive]
3210pub struct HttpHeader {
3211 pub name: String,
3213 pub value: String,
3215 #[serde_as(deserialize_as = "DefaultOnError")]
3221 #[schemars(extend("x-deserialize-default-on-error" = true))]
3222 #[serde(default)]
3223 #[serde(rename = "_meta")]
3224 pub meta: Option<Meta>,
3225}
3226
3227impl HttpHeader {
3228 #[must_use]
3230 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3231 Self {
3232 name: name.into(),
3233 value: value.into(),
3234 meta: None,
3235 }
3236 }
3237
3238 #[must_use]
3244 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3245 self.meta = meta.into_option();
3246 self
3247 }
3248}
3249
3250#[serde_as]
3258#[skip_serializing_none]
3259#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3260#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3261#[serde(rename_all = "camelCase")]
3262#[non_exhaustive]
3263pub struct PromptRequest {
3264 pub session_id: SessionId,
3266 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3280 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3281 pub prompt: Vec<ContentBlock>,
3282 #[serde_as(deserialize_as = "DefaultOnError")]
3288 #[schemars(extend("x-deserialize-default-on-error" = true))]
3289 #[serde(default)]
3290 #[serde(rename = "_meta")]
3291 pub meta: Option<Meta>,
3292}
3293
3294impl PromptRequest {
3295 #[must_use]
3297 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3298 Self {
3299 session_id: session_id.into(),
3300 prompt,
3301 meta: None,
3302 }
3303 }
3304
3305 #[must_use]
3311 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3312 self.meta = meta.into_option();
3313 self
3314 }
3315}
3316
3317#[serde_as]
3321#[skip_serializing_none]
3322#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3323#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3324#[serde(rename_all = "camelCase")]
3325#[non_exhaustive]
3326pub struct PromptResponse {
3327 pub stop_reason: StopReason,
3329 #[cfg(feature = "unstable_end_turn_token_usage")]
3335 #[serde_as(deserialize_as = "DefaultOnError")]
3336 #[schemars(extend("x-deserialize-default-on-error" = true))]
3337 #[serde(default)]
3338 pub usage: Option<Usage>,
3339 #[serde_as(deserialize_as = "DefaultOnError")]
3345 #[schemars(extend("x-deserialize-default-on-error" = true))]
3346 #[serde(default)]
3347 #[serde(rename = "_meta")]
3348 pub meta: Option<Meta>,
3349}
3350
3351impl PromptResponse {
3352 #[must_use]
3354 pub fn new(stop_reason: StopReason) -> Self {
3355 Self {
3356 stop_reason,
3357 #[cfg(feature = "unstable_end_turn_token_usage")]
3358 usage: None,
3359 meta: None,
3360 }
3361 }
3362
3363 #[cfg(feature = "unstable_end_turn_token_usage")]
3369 #[must_use]
3370 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3371 self.usage = usage.into_option();
3372 self
3373 }
3374
3375 #[must_use]
3381 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3382 self.meta = meta.into_option();
3383 self
3384 }
3385}
3386
3387#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3391#[serde(rename_all = "snake_case")]
3392#[non_exhaustive]
3393pub enum StopReason {
3394 EndTurn,
3396 MaxTokens,
3398 MaxTurnRequests,
3401 Refusal,
3405 Cancelled,
3412}
3413
3414#[cfg(feature = "unstable_end_turn_token_usage")]
3420#[serde_as]
3421#[skip_serializing_none]
3422#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3423#[serde(rename_all = "camelCase")]
3424#[non_exhaustive]
3425pub struct Usage {
3426 pub total_tokens: u64,
3428 pub input_tokens: u64,
3430 pub output_tokens: u64,
3432 #[serde_as(deserialize_as = "DefaultOnError")]
3434 #[schemars(extend("x-deserialize-default-on-error" = true))]
3435 #[serde(default)]
3436 pub thought_tokens: Option<u64>,
3437 #[serde_as(deserialize_as = "DefaultOnError")]
3439 #[schemars(extend("x-deserialize-default-on-error" = true))]
3440 #[serde(default)]
3441 pub cached_read_tokens: Option<u64>,
3442 #[serde_as(deserialize_as = "DefaultOnError")]
3444 #[schemars(extend("x-deserialize-default-on-error" = true))]
3445 #[serde(default)]
3446 pub cached_write_tokens: Option<u64>,
3447 #[serde_as(deserialize_as = "DefaultOnError")]
3453 #[schemars(extend("x-deserialize-default-on-error" = true))]
3454 #[serde(default)]
3455 #[serde(rename = "_meta")]
3456 pub meta: Option<Meta>,
3457}
3458
3459#[cfg(feature = "unstable_end_turn_token_usage")]
3460impl Usage {
3461 #[must_use]
3463 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3464 Self {
3465 total_tokens,
3466 input_tokens,
3467 output_tokens,
3468 thought_tokens: None,
3469 cached_read_tokens: None,
3470 cached_write_tokens: None,
3471 meta: None,
3472 }
3473 }
3474
3475 #[must_use]
3477 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3478 self.thought_tokens = thought_tokens.into_option();
3479 self
3480 }
3481
3482 #[must_use]
3484 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3485 self.cached_read_tokens = cached_read_tokens.into_option();
3486 self
3487 }
3488
3489 #[must_use]
3491 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3492 self.cached_write_tokens = cached_write_tokens.into_option();
3493 self
3494 }
3495
3496 #[must_use]
3502 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3503 self.meta = meta.into_option();
3504 self
3505 }
3506}
3507
3508#[cfg(feature = "unstable_llm_providers")]
3521#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3522#[serde(rename_all = "snake_case")]
3523#[non_exhaustive]
3524#[expect(clippy::doc_markdown)]
3525pub enum LlmProtocol {
3526 Anthropic,
3528 #[serde(rename = "openai")]
3530 OpenAi,
3531 Azure,
3533 Vertex,
3535 Bedrock,
3537 #[serde(untagged)]
3539 Other(String),
3540}
3541
3542#[cfg(feature = "unstable_llm_providers")]
3548#[serde_as]
3549#[skip_serializing_none]
3550#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3551#[serde(rename_all = "camelCase")]
3552#[non_exhaustive]
3553pub struct ProviderCurrentConfig {
3554 pub api_type: LlmProtocol,
3556 pub base_url: String,
3558 #[serde_as(deserialize_as = "DefaultOnError")]
3564 #[schemars(extend("x-deserialize-default-on-error" = true))]
3565 #[serde(default)]
3566 #[serde(rename = "_meta")]
3567 pub meta: Option<Meta>,
3568}
3569
3570#[cfg(feature = "unstable_llm_providers")]
3571impl ProviderCurrentConfig {
3572 #[must_use]
3574 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3575 Self {
3576 api_type,
3577 base_url: base_url.into(),
3578 meta: None,
3579 }
3580 }
3581
3582 #[must_use]
3588 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3589 self.meta = meta.into_option();
3590 self
3591 }
3592}
3593
3594#[cfg(feature = "unstable_llm_providers")]
3600#[serde_as]
3601#[skip_serializing_none]
3602#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3603#[serde(rename_all = "camelCase")]
3604#[non_exhaustive]
3605pub struct ProviderInfo {
3606 pub id: String,
3608 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3610 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3611 pub supported: Vec<LlmProtocol>,
3612 pub required: bool,
3615 #[serde_as(deserialize_as = "DefaultOnError")]
3618 #[schemars(extend("x-deserialize-default-on-error" = true))]
3619 #[serde(default)]
3620 pub current: Option<ProviderCurrentConfig>,
3621 #[serde_as(deserialize_as = "DefaultOnError")]
3627 #[schemars(extend("x-deserialize-default-on-error" = true))]
3628 #[serde(default)]
3629 #[serde(rename = "_meta")]
3630 pub meta: Option<Meta>,
3631}
3632
3633#[cfg(feature = "unstable_llm_providers")]
3634impl ProviderInfo {
3635 #[must_use]
3637 pub fn new(
3638 id: impl Into<String>,
3639 supported: Vec<LlmProtocol>,
3640 required: bool,
3641 current: impl IntoOption<ProviderCurrentConfig>,
3642 ) -> Self {
3643 Self {
3644 id: id.into(),
3645 supported,
3646 required,
3647 current: current.into_option(),
3648 meta: None,
3649 }
3650 }
3651
3652 #[must_use]
3658 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3659 self.meta = meta.into_option();
3660 self
3661 }
3662}
3663
3664#[cfg(feature = "unstable_llm_providers")]
3670#[serde_as]
3671#[skip_serializing_none]
3672#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3673#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3674#[serde(rename_all = "camelCase")]
3675#[non_exhaustive]
3676pub struct ListProvidersRequest {
3677 #[serde_as(deserialize_as = "DefaultOnError")]
3683 #[schemars(extend("x-deserialize-default-on-error" = true))]
3684 #[serde(default)]
3685 #[serde(rename = "_meta")]
3686 pub meta: Option<Meta>,
3687}
3688
3689#[cfg(feature = "unstable_llm_providers")]
3690impl ListProvidersRequest {
3691 #[must_use]
3693 pub fn new() -> Self {
3694 Self::default()
3695 }
3696
3697 #[must_use]
3703 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3704 self.meta = meta.into_option();
3705 self
3706 }
3707}
3708
3709#[cfg(feature = "unstable_llm_providers")]
3715#[serde_as]
3716#[skip_serializing_none]
3717#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3718#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3719#[serde(rename_all = "camelCase")]
3720#[non_exhaustive]
3721pub struct ListProvidersResponse {
3722 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3724 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3725 pub providers: Vec<ProviderInfo>,
3726 #[serde_as(deserialize_as = "DefaultOnError")]
3732 #[schemars(extend("x-deserialize-default-on-error" = true))]
3733 #[serde(default)]
3734 #[serde(rename = "_meta")]
3735 pub meta: Option<Meta>,
3736}
3737
3738#[cfg(feature = "unstable_llm_providers")]
3739impl ListProvidersResponse {
3740 #[must_use]
3742 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3743 Self {
3744 providers,
3745 meta: None,
3746 }
3747 }
3748
3749 #[must_use]
3755 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3756 self.meta = meta.into_option();
3757 self
3758 }
3759}
3760
3761#[cfg(feature = "unstable_llm_providers")]
3769#[serde_as]
3770#[skip_serializing_none]
3771#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3772#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3773#[serde(rename_all = "camelCase")]
3774#[non_exhaustive]
3775pub struct SetProviderRequest {
3776 pub id: String,
3778 pub api_type: LlmProtocol,
3780 pub base_url: String,
3782 #[serde_as(deserialize_as = "DefaultOnError")]
3785 #[schemars(extend("x-deserialize-default-on-error" = true))]
3786 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3787 pub headers: HashMap<String, String>,
3788 #[serde_as(deserialize_as = "DefaultOnError")]
3794 #[schemars(extend("x-deserialize-default-on-error" = true))]
3795 #[serde(default)]
3796 #[serde(rename = "_meta")]
3797 pub meta: Option<Meta>,
3798}
3799
3800#[cfg(feature = "unstable_llm_providers")]
3801impl SetProviderRequest {
3802 #[must_use]
3804 pub fn new(id: impl Into<String>, api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3805 Self {
3806 id: id.into(),
3807 api_type,
3808 base_url: base_url.into(),
3809 headers: HashMap::new(),
3810 meta: None,
3811 }
3812 }
3813
3814 #[must_use]
3817 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3818 self.headers = headers;
3819 self
3820 }
3821
3822 #[must_use]
3828 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3829 self.meta = meta.into_option();
3830 self
3831 }
3832}
3833
3834#[cfg(feature = "unstable_llm_providers")]
3840#[serde_as]
3841#[skip_serializing_none]
3842#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3843#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3844#[serde(rename_all = "camelCase")]
3845#[non_exhaustive]
3846pub struct SetProviderResponse {
3847 #[serde_as(deserialize_as = "DefaultOnError")]
3853 #[schemars(extend("x-deserialize-default-on-error" = true))]
3854 #[serde(default)]
3855 #[serde(rename = "_meta")]
3856 pub meta: Option<Meta>,
3857}
3858
3859#[cfg(feature = "unstable_llm_providers")]
3860impl SetProviderResponse {
3861 #[must_use]
3863 pub fn new() -> Self {
3864 Self::default()
3865 }
3866
3867 #[must_use]
3873 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3874 self.meta = meta.into_option();
3875 self
3876 }
3877}
3878
3879#[cfg(feature = "unstable_llm_providers")]
3885#[serde_as]
3886#[skip_serializing_none]
3887#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3888#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3889#[serde(rename_all = "camelCase")]
3890#[non_exhaustive]
3891pub struct DisableProviderRequest {
3892 pub id: String,
3894 #[serde_as(deserialize_as = "DefaultOnError")]
3900 #[schemars(extend("x-deserialize-default-on-error" = true))]
3901 #[serde(default)]
3902 #[serde(rename = "_meta")]
3903 pub meta: Option<Meta>,
3904}
3905
3906#[cfg(feature = "unstable_llm_providers")]
3907impl DisableProviderRequest {
3908 #[must_use]
3910 pub fn new(id: impl Into<String>) -> Self {
3911 Self {
3912 id: id.into(),
3913 meta: None,
3914 }
3915 }
3916
3917 #[must_use]
3923 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3924 self.meta = meta.into_option();
3925 self
3926 }
3927}
3928
3929#[cfg(feature = "unstable_llm_providers")]
3935#[serde_as]
3936#[skip_serializing_none]
3937#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3938#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3939#[serde(rename_all = "camelCase")]
3940#[non_exhaustive]
3941pub struct DisableProviderResponse {
3942 #[serde_as(deserialize_as = "DefaultOnError")]
3948 #[schemars(extend("x-deserialize-default-on-error" = true))]
3949 #[serde(default)]
3950 #[serde(rename = "_meta")]
3951 pub meta: Option<Meta>,
3952}
3953
3954#[cfg(feature = "unstable_llm_providers")]
3955impl DisableProviderResponse {
3956 #[must_use]
3958 pub fn new() -> Self {
3959 Self::default()
3960 }
3961
3962 #[must_use]
3968 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3969 self.meta = meta.into_option();
3970 self
3971 }
3972}
3973
3974#[serde_as]
3983#[skip_serializing_none]
3984#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3985#[serde(rename_all = "camelCase")]
3986#[non_exhaustive]
3987pub struct AgentCapabilities {
3988 #[serde_as(deserialize_as = "DefaultOnError")]
3990 #[schemars(extend("x-deserialize-default-on-error" = true))]
3991 #[serde(default)]
3992 pub load_session: bool,
3993 #[serde_as(deserialize_as = "DefaultOnError")]
3995 #[schemars(extend("x-deserialize-default-on-error" = true))]
3996 #[serde(default)]
3997 pub prompt_capabilities: PromptCapabilities,
3998 #[serde_as(deserialize_as = "DefaultOnError")]
4000 #[schemars(extend("x-deserialize-default-on-error" = true))]
4001 #[serde(default)]
4002 pub mcp_capabilities: McpCapabilities,
4003 #[serde_as(deserialize_as = "DefaultOnError")]
4005 #[schemars(extend("x-deserialize-default-on-error" = true))]
4006 #[serde(default)]
4007 pub session_capabilities: SessionCapabilities,
4008 #[serde_as(deserialize_as = "DefaultOnError")]
4010 #[schemars(extend("x-deserialize-default-on-error" = true))]
4011 #[serde(default)]
4012 pub auth: AgentAuthCapabilities,
4013 #[cfg(feature = "unstable_llm_providers")]
4021 #[serde_as(deserialize_as = "DefaultOnError")]
4022 #[schemars(extend("x-deserialize-default-on-error" = true))]
4023 #[serde(default)]
4024 pub providers: Option<ProvidersCapabilities>,
4025 #[cfg(feature = "unstable_nes")]
4031 #[serde_as(deserialize_as = "DefaultOnError")]
4032 #[schemars(extend("x-deserialize-default-on-error" = true))]
4033 #[serde(default)]
4034 pub nes: Option<NesCapabilities>,
4035 #[cfg(feature = "unstable_nes")]
4041 #[serde_as(deserialize_as = "DefaultOnError")]
4042 #[schemars(extend("x-deserialize-default-on-error" = true))]
4043 #[serde(default)]
4044 pub position_encoding: Option<PositionEncodingKind>,
4045 #[serde_as(deserialize_as = "DefaultOnError")]
4051 #[schemars(extend("x-deserialize-default-on-error" = true))]
4052 #[serde(default)]
4053 #[serde(rename = "_meta")]
4054 pub meta: Option<Meta>,
4055}
4056
4057impl AgentCapabilities {
4058 #[must_use]
4060 pub fn new() -> Self {
4061 Self::default()
4062 }
4063
4064 #[must_use]
4066 pub fn load_session(mut self, load_session: bool) -> Self {
4067 self.load_session = load_session;
4068 self
4069 }
4070
4071 #[must_use]
4073 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
4074 self.prompt_capabilities = prompt_capabilities;
4075 self
4076 }
4077
4078 #[must_use]
4080 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
4081 self.mcp_capabilities = mcp_capabilities;
4082 self
4083 }
4084
4085 #[must_use]
4087 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
4088 self.session_capabilities = session_capabilities;
4089 self
4090 }
4091
4092 #[must_use]
4094 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
4095 self.auth = auth;
4096 self
4097 }
4098
4099 #[cfg(feature = "unstable_llm_providers")]
4105 #[must_use]
4106 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
4107 self.providers = providers.into_option();
4108 self
4109 }
4110
4111 #[cfg(feature = "unstable_nes")]
4117 #[must_use]
4118 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
4119 self.nes = nes.into_option();
4120 self
4121 }
4122
4123 #[cfg(feature = "unstable_nes")]
4127 #[must_use]
4128 pub fn position_encoding(
4129 mut self,
4130 position_encoding: impl IntoOption<PositionEncodingKind>,
4131 ) -> Self {
4132 self.position_encoding = position_encoding.into_option();
4133 self
4134 }
4135
4136 #[must_use]
4142 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4143 self.meta = meta.into_option();
4144 self
4145 }
4146}
4147
4148#[cfg(feature = "unstable_llm_providers")]
4156#[serde_as]
4157#[skip_serializing_none]
4158#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4159#[non_exhaustive]
4160pub struct ProvidersCapabilities {
4161 #[serde_as(deserialize_as = "DefaultOnError")]
4167 #[schemars(extend("x-deserialize-default-on-error" = true))]
4168 #[serde(default)]
4169 #[serde(rename = "_meta")]
4170 pub meta: Option<Meta>,
4171}
4172
4173#[cfg(feature = "unstable_llm_providers")]
4174impl ProvidersCapabilities {
4175 #[must_use]
4177 pub fn new() -> Self {
4178 Self::default()
4179 }
4180
4181 #[must_use]
4187 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4188 self.meta = meta.into_option();
4189 self
4190 }
4191}
4192
4193#[serde_as]
4203#[skip_serializing_none]
4204#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4205#[serde(rename_all = "camelCase")]
4206#[non_exhaustive]
4207pub struct SessionCapabilities {
4208 #[serde_as(deserialize_as = "DefaultOnError")]
4210 #[schemars(extend("x-deserialize-default-on-error" = true))]
4211 #[serde(default)]
4212 pub list: Option<SessionListCapabilities>,
4213 #[serde_as(deserialize_as = "DefaultOnError")]
4218 #[schemars(extend("x-deserialize-default-on-error" = true))]
4219 #[serde(default)]
4220 pub delete: Option<SessionDeleteCapabilities>,
4221 #[serde_as(deserialize_as = "DefaultOnError")]
4227 #[schemars(extend("x-deserialize-default-on-error" = true))]
4228 #[serde(default)]
4229 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4230 #[cfg(feature = "unstable_session_fork")]
4236 #[serde_as(deserialize_as = "DefaultOnError")]
4237 #[schemars(extend("x-deserialize-default-on-error" = true))]
4238 #[serde(default)]
4239 pub fork: Option<SessionForkCapabilities>,
4240 #[serde_as(deserialize_as = "DefaultOnError")]
4242 #[schemars(extend("x-deserialize-default-on-error" = true))]
4243 #[serde(default)]
4244 pub resume: Option<SessionResumeCapabilities>,
4245 #[serde_as(deserialize_as = "DefaultOnError")]
4247 #[schemars(extend("x-deserialize-default-on-error" = true))]
4248 #[serde(default)]
4249 pub close: Option<SessionCloseCapabilities>,
4250 #[serde_as(deserialize_as = "DefaultOnError")]
4256 #[schemars(extend("x-deserialize-default-on-error" = true))]
4257 #[serde(default)]
4258 #[serde(rename = "_meta")]
4259 pub meta: Option<Meta>,
4260}
4261
4262impl SessionCapabilities {
4263 #[must_use]
4265 pub fn new() -> Self {
4266 Self::default()
4267 }
4268
4269 #[must_use]
4271 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4272 self.list = list.into_option();
4273 self
4274 }
4275
4276 #[must_use]
4281 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4282 self.delete = delete.into_option();
4283 self
4284 }
4285
4286 #[must_use]
4292 pub fn additional_directories(
4293 mut self,
4294 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4295 ) -> Self {
4296 self.additional_directories = additional_directories.into_option();
4297 self
4298 }
4299
4300 #[cfg(feature = "unstable_session_fork")]
4301 #[must_use]
4303 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4304 self.fork = fork.into_option();
4305 self
4306 }
4307
4308 #[must_use]
4310 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4311 self.resume = resume.into_option();
4312 self
4313 }
4314
4315 #[must_use]
4317 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4318 self.close = close.into_option();
4319 self
4320 }
4321
4322 #[must_use]
4328 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4329 self.meta = meta.into_option();
4330 self
4331 }
4332}
4333
4334#[serde_as]
4338#[skip_serializing_none]
4339#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4340#[non_exhaustive]
4341pub struct SessionListCapabilities {
4342 #[serde_as(deserialize_as = "DefaultOnError")]
4348 #[schemars(extend("x-deserialize-default-on-error" = true))]
4349 #[serde(default)]
4350 #[serde(rename = "_meta")]
4351 pub meta: Option<Meta>,
4352}
4353
4354impl SessionListCapabilities {
4355 #[must_use]
4357 pub fn new() -> Self {
4358 Self::default()
4359 }
4360
4361 #[must_use]
4367 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4368 self.meta = meta.into_option();
4369 self
4370 }
4371}
4372
4373#[serde_as]
4377#[skip_serializing_none]
4378#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4379#[non_exhaustive]
4380pub struct SessionDeleteCapabilities {
4381 #[serde_as(deserialize_as = "DefaultOnError")]
4387 #[schemars(extend("x-deserialize-default-on-error" = true))]
4388 #[serde(default)]
4389 #[serde(rename = "_meta")]
4390 pub meta: Option<Meta>,
4391}
4392
4393impl SessionDeleteCapabilities {
4394 #[must_use]
4396 pub fn new() -> Self {
4397 Self::default()
4398 }
4399
4400 #[must_use]
4406 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4407 self.meta = meta.into_option();
4408 self
4409 }
4410}
4411
4412#[serde_as]
4419#[skip_serializing_none]
4420#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4421#[non_exhaustive]
4422pub struct SessionAdditionalDirectoriesCapabilities {
4423 #[serde_as(deserialize_as = "DefaultOnError")]
4429 #[schemars(extend("x-deserialize-default-on-error" = true))]
4430 #[serde(default)]
4431 #[serde(rename = "_meta")]
4432 pub meta: Option<Meta>,
4433}
4434
4435impl SessionAdditionalDirectoriesCapabilities {
4436 #[must_use]
4438 pub fn new() -> Self {
4439 Self::default()
4440 }
4441
4442 #[must_use]
4448 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4449 self.meta = meta.into_option();
4450 self
4451 }
4452}
4453
4454#[cfg(feature = "unstable_session_fork")]
4462#[serde_as]
4463#[skip_serializing_none]
4464#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4465#[non_exhaustive]
4466pub struct SessionForkCapabilities {
4467 #[serde_as(deserialize_as = "DefaultOnError")]
4473 #[schemars(extend("x-deserialize-default-on-error" = true))]
4474 #[serde(default)]
4475 #[serde(rename = "_meta")]
4476 pub meta: Option<Meta>,
4477}
4478
4479#[cfg(feature = "unstable_session_fork")]
4480impl SessionForkCapabilities {
4481 #[must_use]
4483 pub fn new() -> Self {
4484 Self::default()
4485 }
4486
4487 #[must_use]
4493 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4494 self.meta = meta.into_option();
4495 self
4496 }
4497}
4498
4499#[serde_as]
4503#[skip_serializing_none]
4504#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4505#[non_exhaustive]
4506pub struct SessionResumeCapabilities {
4507 #[serde_as(deserialize_as = "DefaultOnError")]
4513 #[schemars(extend("x-deserialize-default-on-error" = true))]
4514 #[serde(default)]
4515 #[serde(rename = "_meta")]
4516 pub meta: Option<Meta>,
4517}
4518
4519impl SessionResumeCapabilities {
4520 #[must_use]
4522 pub fn new() -> Self {
4523 Self::default()
4524 }
4525
4526 #[must_use]
4532 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4533 self.meta = meta.into_option();
4534 self
4535 }
4536}
4537
4538#[serde_as]
4542#[skip_serializing_none]
4543#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4544#[non_exhaustive]
4545pub struct SessionCloseCapabilities {
4546 #[serde_as(deserialize_as = "DefaultOnError")]
4552 #[schemars(extend("x-deserialize-default-on-error" = true))]
4553 #[serde(default)]
4554 #[serde(rename = "_meta")]
4555 pub meta: Option<Meta>,
4556}
4557
4558impl SessionCloseCapabilities {
4559 #[must_use]
4561 pub fn new() -> Self {
4562 Self::default()
4563 }
4564
4565 #[must_use]
4571 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4572 self.meta = meta.into_option();
4573 self
4574 }
4575}
4576
4577#[serde_as]
4590#[skip_serializing_none]
4591#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4592#[serde(rename_all = "camelCase")]
4593#[non_exhaustive]
4594pub struct PromptCapabilities {
4595 #[serde_as(deserialize_as = "DefaultOnError")]
4597 #[schemars(extend("x-deserialize-default-on-error" = true))]
4598 #[serde(default)]
4599 pub image: bool,
4600 #[serde_as(deserialize_as = "DefaultOnError")]
4602 #[schemars(extend("x-deserialize-default-on-error" = true))]
4603 #[serde(default)]
4604 pub audio: bool,
4605 #[serde_as(deserialize_as = "DefaultOnError")]
4610 #[schemars(extend("x-deserialize-default-on-error" = true))]
4611 #[serde(default)]
4612 pub embedded_context: bool,
4613 #[serde_as(deserialize_as = "DefaultOnError")]
4619 #[schemars(extend("x-deserialize-default-on-error" = true))]
4620 #[serde(default)]
4621 #[serde(rename = "_meta")]
4622 pub meta: Option<Meta>,
4623}
4624
4625impl PromptCapabilities {
4626 #[must_use]
4628 pub fn new() -> Self {
4629 Self::default()
4630 }
4631
4632 #[must_use]
4634 pub fn image(mut self, image: bool) -> Self {
4635 self.image = image;
4636 self
4637 }
4638
4639 #[must_use]
4641 pub fn audio(mut self, audio: bool) -> Self {
4642 self.audio = audio;
4643 self
4644 }
4645
4646 #[must_use]
4651 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4652 self.embedded_context = embedded_context;
4653 self
4654 }
4655
4656 #[must_use]
4662 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4663 self.meta = meta.into_option();
4664 self
4665 }
4666}
4667
4668#[serde_as]
4670#[skip_serializing_none]
4671#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4672#[serde(rename_all = "camelCase")]
4673#[non_exhaustive]
4674pub struct McpCapabilities {
4675 #[serde_as(deserialize_as = "DefaultOnError")]
4677 #[schemars(extend("x-deserialize-default-on-error" = true))]
4678 #[serde(default)]
4679 pub http: bool,
4680 #[serde_as(deserialize_as = "DefaultOnError")]
4682 #[schemars(extend("x-deserialize-default-on-error" = true))]
4683 #[serde(default)]
4684 pub sse: bool,
4685 #[cfg(feature = "unstable_mcp_over_acp")]
4691 #[serde_as(deserialize_as = "DefaultOnError")]
4692 #[schemars(extend("x-deserialize-default-on-error" = true))]
4693 #[serde(default)]
4694 pub acp: bool,
4695 #[serde_as(deserialize_as = "DefaultOnError")]
4701 #[schemars(extend("x-deserialize-default-on-error" = true))]
4702 #[serde(default)]
4703 #[serde(rename = "_meta")]
4704 pub meta: Option<Meta>,
4705}
4706
4707impl McpCapabilities {
4708 #[must_use]
4710 pub fn new() -> Self {
4711 Self::default()
4712 }
4713
4714 #[must_use]
4716 pub fn http(mut self, http: bool) -> Self {
4717 self.http = http;
4718 self
4719 }
4720
4721 #[must_use]
4723 pub fn sse(mut self, sse: bool) -> Self {
4724 self.sse = sse;
4725 self
4726 }
4727
4728 #[cfg(feature = "unstable_mcp_over_acp")]
4734 #[must_use]
4735 pub fn acp(mut self, acp: bool) -> Self {
4736 self.acp = acp;
4737 self
4738 }
4739
4740 #[must_use]
4746 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4747 self.meta = meta.into_option();
4748 self
4749 }
4750}
4751
4752#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4758#[non_exhaustive]
4759pub struct AgentMethodNames {
4760 pub initialize: &'static str,
4762 pub authenticate: &'static str,
4764 #[cfg(feature = "unstable_llm_providers")]
4766 pub providers_list: &'static str,
4767 #[cfg(feature = "unstable_llm_providers")]
4769 pub providers_set: &'static str,
4770 #[cfg(feature = "unstable_llm_providers")]
4772 pub providers_disable: &'static str,
4773 pub session_new: &'static str,
4775 pub session_load: &'static str,
4777 pub session_set_mode: &'static str,
4779 pub session_set_config_option: &'static str,
4781 pub session_prompt: &'static str,
4783 pub session_cancel: &'static str,
4785 #[cfg(feature = "unstable_mcp_over_acp")]
4787 pub mcp_message: &'static str,
4788 pub session_list: &'static str,
4790 pub session_delete: &'static str,
4792 #[cfg(feature = "unstable_session_fork")]
4794 pub session_fork: &'static str,
4795 pub session_resume: &'static str,
4797 pub session_close: &'static str,
4799 pub logout: &'static str,
4801 #[cfg(feature = "unstable_nes")]
4803 pub nes_start: &'static str,
4804 #[cfg(feature = "unstable_nes")]
4806 pub nes_suggest: &'static str,
4807 #[cfg(feature = "unstable_nes")]
4809 pub nes_accept: &'static str,
4810 #[cfg(feature = "unstable_nes")]
4812 pub nes_reject: &'static str,
4813 #[cfg(feature = "unstable_nes")]
4815 pub nes_close: &'static str,
4816 #[cfg(feature = "unstable_nes")]
4818 pub document_did_open: &'static str,
4819 #[cfg(feature = "unstable_nes")]
4821 pub document_did_change: &'static str,
4822 #[cfg(feature = "unstable_nes")]
4824 pub document_did_close: &'static str,
4825 #[cfg(feature = "unstable_nes")]
4827 pub document_did_save: &'static str,
4828 #[cfg(feature = "unstable_nes")]
4830 pub document_did_focus: &'static str,
4831}
4832
4833pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4835 initialize: INITIALIZE_METHOD_NAME,
4836 authenticate: AUTHENTICATE_METHOD_NAME,
4837 #[cfg(feature = "unstable_llm_providers")]
4838 providers_list: PROVIDERS_LIST_METHOD_NAME,
4839 #[cfg(feature = "unstable_llm_providers")]
4840 providers_set: PROVIDERS_SET_METHOD_NAME,
4841 #[cfg(feature = "unstable_llm_providers")]
4842 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4843 session_new: SESSION_NEW_METHOD_NAME,
4844 session_load: SESSION_LOAD_METHOD_NAME,
4845 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4846 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4847 session_prompt: SESSION_PROMPT_METHOD_NAME,
4848 session_cancel: SESSION_CANCEL_METHOD_NAME,
4849 #[cfg(feature = "unstable_mcp_over_acp")]
4850 mcp_message: MCP_MESSAGE_METHOD_NAME,
4851 session_list: SESSION_LIST_METHOD_NAME,
4852 session_delete: SESSION_DELETE_METHOD_NAME,
4853 #[cfg(feature = "unstable_session_fork")]
4854 session_fork: SESSION_FORK_METHOD_NAME,
4855 session_resume: SESSION_RESUME_METHOD_NAME,
4856 session_close: SESSION_CLOSE_METHOD_NAME,
4857 logout: LOGOUT_METHOD_NAME,
4858 #[cfg(feature = "unstable_nes")]
4859 nes_start: NES_START_METHOD_NAME,
4860 #[cfg(feature = "unstable_nes")]
4861 nes_suggest: NES_SUGGEST_METHOD_NAME,
4862 #[cfg(feature = "unstable_nes")]
4863 nes_accept: NES_ACCEPT_METHOD_NAME,
4864 #[cfg(feature = "unstable_nes")]
4865 nes_reject: NES_REJECT_METHOD_NAME,
4866 #[cfg(feature = "unstable_nes")]
4867 nes_close: NES_CLOSE_METHOD_NAME,
4868 #[cfg(feature = "unstable_nes")]
4869 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4870 #[cfg(feature = "unstable_nes")]
4871 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4872 #[cfg(feature = "unstable_nes")]
4873 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4874 #[cfg(feature = "unstable_nes")]
4875 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4876 #[cfg(feature = "unstable_nes")]
4877 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4878};
4879
4880pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4882pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4884#[cfg(feature = "unstable_llm_providers")]
4886pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4887#[cfg(feature = "unstable_llm_providers")]
4889pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4890#[cfg(feature = "unstable_llm_providers")]
4892pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4893pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4895pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4897pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4899pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4901pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4903pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4905pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4907pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4909#[cfg(feature = "unstable_session_fork")]
4911pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4912pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4914pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4916pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4918
4919#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4926#[serde(untagged)]
4927#[schemars(inline)]
4928#[non_exhaustive]
4929#[allow(clippy::large_enum_variant)]
4930pub enum ClientRequest {
4931 InitializeRequest(InitializeRequest),
4942 AuthenticateRequest(AuthenticateRequest),
4952 #[cfg(feature = "unstable_llm_providers")]
4958 ListProvidersRequest(ListProvidersRequest),
4959 #[cfg(feature = "unstable_llm_providers")]
4965 SetProviderRequest(SetProviderRequest),
4966 #[cfg(feature = "unstable_llm_providers")]
4972 DisableProviderRequest(DisableProviderRequest),
4973 LogoutRequest(LogoutRequest),
4978 NewSessionRequest(NewSessionRequest),
4991 LoadSessionRequest(LoadSessionRequest),
5002 ListSessionsRequest(ListSessionsRequest),
5008 DeleteSessionRequest(DeleteSessionRequest),
5012 #[cfg(feature = "unstable_session_fork")]
5013 ForkSessionRequest(ForkSessionRequest),
5025 ResumeSessionRequest(ResumeSessionRequest),
5032 CloseSessionRequest(CloseSessionRequest),
5039 SetSessionModeRequest(SetSessionModeRequest),
5053 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5055 PromptRequest(PromptRequest),
5067 #[cfg(feature = "unstable_nes")]
5068 StartNesRequest(StartNesRequest),
5074 #[cfg(feature = "unstable_nes")]
5075 SuggestNesRequest(SuggestNesRequest),
5081 #[cfg(feature = "unstable_nes")]
5082 CloseNesRequest(CloseNesRequest),
5091 #[cfg(feature = "unstable_mcp_over_acp")]
5097 MessageMcpRequest(MessageMcpRequest),
5098 ExtMethodRequest(ExtRequest),
5105}
5106
5107impl ClientRequest {
5108 #[must_use]
5110 pub fn method(&self) -> &str {
5111 match self {
5112 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5113 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5114 #[cfg(feature = "unstable_llm_providers")]
5115 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5116 #[cfg(feature = "unstable_llm_providers")]
5117 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
5118 #[cfg(feature = "unstable_llm_providers")]
5119 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5120 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5121 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5122 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5123 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5124 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5125 #[cfg(feature = "unstable_session_fork")]
5126 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5127 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5128 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5129 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
5130 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5131 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5132 #[cfg(feature = "unstable_nes")]
5133 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5134 #[cfg(feature = "unstable_nes")]
5135 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5136 #[cfg(feature = "unstable_nes")]
5137 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5138 #[cfg(feature = "unstable_mcp_over_acp")]
5139 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5140 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5141 }
5142 }
5143}
5144
5145#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5152#[serde(untagged)]
5153#[schemars(inline)]
5154#[non_exhaustive]
5155#[allow(clippy::large_enum_variant)]
5156pub enum AgentResponse {
5157 InitializeResponse(InitializeResponse),
5159 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5161 #[cfg(feature = "unstable_llm_providers")]
5163 ListProvidersResponse(ListProvidersResponse),
5164 #[cfg(feature = "unstable_llm_providers")]
5166 SetProviderResponse(#[serde(default)] SetProviderResponse),
5167 #[cfg(feature = "unstable_llm_providers")]
5169 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5170 LogoutResponse(#[serde(default)] LogoutResponse),
5172 NewSessionResponse(NewSessionResponse),
5174 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5176 ListSessionsResponse(ListSessionsResponse),
5178 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5180 #[cfg(feature = "unstable_session_fork")]
5182 ForkSessionResponse(ForkSessionResponse),
5183 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5185 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5187 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5189 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5191 PromptResponse(PromptResponse),
5193 #[cfg(feature = "unstable_nes")]
5195 StartNesResponse(StartNesResponse),
5196 #[cfg(feature = "unstable_nes")]
5198 SuggestNesResponse(SuggestNesResponse),
5199 #[cfg(feature = "unstable_nes")]
5201 CloseNesResponse(#[serde(default)] CloseNesResponse),
5202 ExtMethodResponse(ExtResponse),
5204 #[cfg(feature = "unstable_mcp_over_acp")]
5206 MessageMcpResponse(MessageMcpResponse),
5207}
5208
5209#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5216#[serde(untagged)]
5217#[schemars(inline)]
5218#[non_exhaustive]
5219#[allow(clippy::large_enum_variant)]
5220pub enum ClientNotification {
5221 CancelNotification(CancelNotification),
5233 #[cfg(feature = "unstable_nes")]
5234 DidOpenDocumentNotification(DidOpenDocumentNotification),
5238 #[cfg(feature = "unstable_nes")]
5239 DidChangeDocumentNotification(DidChangeDocumentNotification),
5243 #[cfg(feature = "unstable_nes")]
5244 DidCloseDocumentNotification(DidCloseDocumentNotification),
5248 #[cfg(feature = "unstable_nes")]
5249 DidSaveDocumentNotification(DidSaveDocumentNotification),
5253 #[cfg(feature = "unstable_nes")]
5254 DidFocusDocumentNotification(DidFocusDocumentNotification),
5258 #[cfg(feature = "unstable_nes")]
5259 AcceptNesNotification(AcceptNesNotification),
5263 #[cfg(feature = "unstable_nes")]
5264 RejectNesNotification(RejectNesNotification),
5268 #[cfg(feature = "unstable_mcp_over_acp")]
5274 MessageMcpNotification(MessageMcpNotification),
5275 ExtNotification(ExtNotification),
5282}
5283
5284impl ClientNotification {
5285 #[must_use]
5287 pub fn method(&self) -> &str {
5288 match self {
5289 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5290 #[cfg(feature = "unstable_nes")]
5291 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5292 #[cfg(feature = "unstable_nes")]
5293 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5294 #[cfg(feature = "unstable_nes")]
5295 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5296 #[cfg(feature = "unstable_nes")]
5297 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5298 #[cfg(feature = "unstable_nes")]
5299 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5300 #[cfg(feature = "unstable_nes")]
5301 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5302 #[cfg(feature = "unstable_nes")]
5303 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5304 #[cfg(feature = "unstable_mcp_over_acp")]
5305 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5306 Self::ExtNotification(ext_notification) => &ext_notification.method,
5307 }
5308 }
5309}
5310
5311#[serde_as]
5315#[skip_serializing_none]
5316#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5317#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5318#[serde(rename_all = "camelCase")]
5319#[non_exhaustive]
5320pub struct CancelNotification {
5321 pub session_id: SessionId,
5323 #[serde_as(deserialize_as = "DefaultOnError")]
5329 #[schemars(extend("x-deserialize-default-on-error" = true))]
5330 #[serde(default)]
5331 #[serde(rename = "_meta")]
5332 pub meta: Option<Meta>,
5333}
5334
5335impl CancelNotification {
5336 #[must_use]
5338 pub fn new(session_id: impl Into<SessionId>) -> Self {
5339 Self {
5340 session_id: session_id.into(),
5341 meta: None,
5342 }
5343 }
5344
5345 #[must_use]
5351 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5352 self.meta = meta.into_option();
5353 self
5354 }
5355}
5356
5357#[cfg(test)]
5358mod test_serialization {
5359 use super::*;
5360 use serde_json::json;
5361
5362 #[cfg(feature = "unstable_boolean_config")]
5363 fn test_meta() -> Meta {
5364 json!({ "source": "test" }).as_object().unwrap().clone()
5365 }
5366
5367 #[cfg(feature = "unstable_boolean_config")]
5368 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5369 serde_json::to_string(value)
5370 .unwrap()
5371 .matches("\"_meta\"")
5372 .count()
5373 }
5374
5375 #[test]
5376 fn test_initialize_capabilities_default_on_malformed_values() {
5377 let request: InitializeRequest = serde_json::from_value(json!({
5378 "protocolVersion": 1,
5379 "clientCapabilities": false
5380 }))
5381 .unwrap();
5382 assert_eq!(request.client_capabilities, ClientCapabilities::default());
5383
5384 let response: InitializeResponse = serde_json::from_value(json!({
5385 "protocolVersion": 1,
5386 "agentCapabilities": false
5387 }))
5388 .unwrap();
5389 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
5390 }
5391
5392 #[test]
5393 fn test_agent_capabilities_default_on_malformed_values() {
5394 let capabilities: AgentCapabilities = serde_json::from_value(json!({
5395 "loadSession": "yes",
5396 "promptCapabilities": {
5397 "image": "yes",
5398 "audio": true,
5399 "embeddedContext": {}
5400 },
5401 "mcpCapabilities": {
5402 "http": "yes",
5403 "sse": true
5404 },
5405 "sessionCapabilities": false,
5406 "auth": false
5407 }))
5408 .unwrap();
5409
5410 assert!(!capabilities.load_session);
5411 assert!(!capabilities.prompt_capabilities.image);
5412 assert!(capabilities.prompt_capabilities.audio);
5413 assert!(!capabilities.prompt_capabilities.embedded_context);
5414 assert!(!capabilities.mcp_capabilities.http);
5415 assert!(capabilities.mcp_capabilities.sse);
5416 assert_eq!(
5417 capabilities.session_capabilities,
5418 SessionCapabilities::default()
5419 );
5420 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
5421 }
5422
5423 #[test]
5424 fn test_mcp_server_stdio_serialization() {
5425 let server = McpServer::Stdio(
5426 McpServerStdio::new("test-server", "/usr/bin/server")
5427 .args(vec!["--port".to_string(), "3000".to_string()])
5428 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5429 );
5430
5431 let json = serde_json::to_value(&server).unwrap();
5432 assert_eq!(
5433 json,
5434 json!({
5435 "name": "test-server",
5436 "command": "/usr/bin/server",
5437 "args": ["--port", "3000"],
5438 "env": [
5439 {
5440 "name": "API_KEY",
5441 "value": "secret123"
5442 }
5443 ]
5444 })
5445 );
5446
5447 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5448 match deserialized {
5449 McpServer::Stdio(McpServerStdio {
5450 name,
5451 command,
5452 args,
5453 env,
5454 meta: _,
5455 }) => {
5456 assert_eq!(name, "test-server");
5457 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5458 assert_eq!(args, vec!["--port", "3000"]);
5459 assert_eq!(env.len(), 1);
5460 assert_eq!(env[0].name, "API_KEY");
5461 assert_eq!(env[0].value, "secret123");
5462 }
5463 _ => panic!("Expected Stdio variant"),
5464 }
5465 }
5466
5467 #[test]
5468 fn test_mcp_server_http_serialization() {
5469 let server = McpServer::Http(
5470 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5471 HttpHeader::new("Authorization", "Bearer token123"),
5472 HttpHeader::new("Content-Type", "application/json"),
5473 ]),
5474 );
5475
5476 let json = serde_json::to_value(&server).unwrap();
5477 assert_eq!(
5478 json,
5479 json!({
5480 "type": "http",
5481 "name": "http-server",
5482 "url": "https://api.example.com",
5483 "headers": [
5484 {
5485 "name": "Authorization",
5486 "value": "Bearer token123"
5487 },
5488 {
5489 "name": "Content-Type",
5490 "value": "application/json"
5491 }
5492 ]
5493 })
5494 );
5495
5496 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5497 match deserialized {
5498 McpServer::Http(McpServerHttp {
5499 name,
5500 url,
5501 headers,
5502 meta: _,
5503 }) => {
5504 assert_eq!(name, "http-server");
5505 assert_eq!(url, "https://api.example.com");
5506 assert_eq!(headers.len(), 2);
5507 assert_eq!(headers[0].name, "Authorization");
5508 assert_eq!(headers[0].value, "Bearer token123");
5509 assert_eq!(headers[1].name, "Content-Type");
5510 assert_eq!(headers[1].value, "application/json");
5511 }
5512 _ => panic!("Expected Http variant"),
5513 }
5514 }
5515
5516 #[cfg(feature = "unstable_mcp_over_acp")]
5517 #[test]
5518 fn test_mcp_server_acp_serialization() {
5519 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5520
5521 let json = serde_json::to_value(&server).unwrap();
5522 assert_eq!(
5523 json,
5524 json!({
5525 "type": "acp",
5526 "name": "project-tools",
5527 "id": "project-tools-id"
5528 })
5529 );
5530
5531 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5532 match deserialized {
5533 McpServer::Acp(McpServerAcp { name, id, meta: _ }) => {
5534 assert_eq!(name, "project-tools");
5535 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5536 }
5537 _ => panic!("Expected Acp variant"),
5538 }
5539 }
5540
5541 #[cfg(feature = "unstable_mcp_over_acp")]
5542 #[test]
5543 fn test_client_mcp_message_method_names() {
5544 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5545
5546 assert_eq!(
5547 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5548 .method(),
5549 "mcp/message"
5550 );
5551 assert_eq!(
5552 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5553 "conn-1",
5554 "notifications/progress"
5555 ))
5556 .method(),
5557 "mcp/message"
5558 );
5559 }
5560
5561 #[cfg(feature = "unstable_mcp_over_acp")]
5562 #[test]
5563 fn test_mcp_server_acp_schema() {
5564 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5565 assert!(json_contains_entry(
5566 &mcp_server_schema,
5567 "const",
5568 &json!("acp")
5569 ));
5570 assert!(json_contains_entry(
5571 &mcp_server_schema,
5572 "$ref",
5573 &json!("#/$defs/McpServerAcp")
5574 ));
5575
5576 let capabilities_schema =
5577 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5578 assert!(json_contains_key(&capabilities_schema, "acp"));
5579 }
5580
5581 #[cfg(feature = "unstable_mcp_over_acp")]
5582 fn json_contains_entry(
5583 value: &serde_json::Value,
5584 key: &str,
5585 expected: &serde_json::Value,
5586 ) -> bool {
5587 match value {
5588 serde_json::Value::Object(map) => {
5589 map.get(key) == Some(expected)
5590 || map
5591 .values()
5592 .any(|value| json_contains_entry(value, key, expected))
5593 }
5594 serde_json::Value::Array(values) => values
5595 .iter()
5596 .any(|value| json_contains_entry(value, key, expected)),
5597 _ => false,
5598 }
5599 }
5600
5601 #[cfg(feature = "unstable_mcp_over_acp")]
5602 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5603 match value {
5604 serde_json::Value::Object(map) => {
5605 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5606 }
5607 serde_json::Value::Array(values) => {
5608 values.iter().any(|value| json_contains_key(value, key))
5609 }
5610 _ => false,
5611 }
5612 }
5613
5614 #[test]
5615 fn test_mcp_server_sse_serialization() {
5616 let server = McpServer::Sse(
5617 McpServerSse::new("sse-server", "https://sse.example.com/events")
5618 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5619 );
5620
5621 let json = serde_json::to_value(&server).unwrap();
5622 assert_eq!(
5623 json,
5624 json!({
5625 "type": "sse",
5626 "name": "sse-server",
5627 "url": "https://sse.example.com/events",
5628 "headers": [
5629 {
5630 "name": "X-API-Key",
5631 "value": "apikey456"
5632 }
5633 ]
5634 })
5635 );
5636
5637 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5638 match deserialized {
5639 McpServer::Sse(McpServerSse {
5640 name,
5641 url,
5642 headers,
5643 meta: _,
5644 }) => {
5645 assert_eq!(name, "sse-server");
5646 assert_eq!(url, "https://sse.example.com/events");
5647 assert_eq!(headers.len(), 1);
5648 assert_eq!(headers[0].name, "X-API-Key");
5649 assert_eq!(headers[0].value, "apikey456");
5650 }
5651 _ => panic!("Expected Sse variant"),
5652 }
5653 }
5654
5655 #[test]
5656 fn test_session_config_option_category_known_variants() {
5657 assert_eq!(
5659 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5660 json!("mode")
5661 );
5662 assert_eq!(
5663 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5664 json!("model")
5665 );
5666 assert_eq!(
5667 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5668 json!("model_config")
5669 );
5670 assert_eq!(
5671 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5672 json!("thought_level")
5673 );
5674
5675 assert_eq!(
5677 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5678 SessionConfigOptionCategory::Mode
5679 );
5680 assert_eq!(
5681 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5682 SessionConfigOptionCategory::Model
5683 );
5684 assert_eq!(
5685 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5686 SessionConfigOptionCategory::ModelConfig
5687 );
5688 assert_eq!(
5689 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5690 SessionConfigOptionCategory::ThoughtLevel
5691 );
5692 }
5693
5694 #[test]
5695 fn test_session_config_option_category_unknown_variants() {
5696 let unknown: SessionConfigOptionCategory =
5698 serde_json::from_str("\"some_future_category\"").unwrap();
5699 assert_eq!(
5700 unknown,
5701 SessionConfigOptionCategory::Other("some_future_category".to_string())
5702 );
5703
5704 let json = serde_json::to_value(&unknown).unwrap();
5706 assert_eq!(json, json!("some_future_category"));
5707 }
5708
5709 #[test]
5710 fn test_session_config_option_category_custom_categories() {
5711 let custom: SessionConfigOptionCategory =
5713 serde_json::from_str("\"_my_custom_category\"").unwrap();
5714 assert_eq!(
5715 custom,
5716 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5717 );
5718
5719 let json = serde_json::to_value(&custom).unwrap();
5721 assert_eq!(json, json!("_my_custom_category"));
5722
5723 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5725 assert_eq!(
5726 deserialized,
5727 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5728 );
5729 }
5730
5731 #[test]
5732 fn test_auth_method_agent_serialization() {
5733 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5734
5735 let json = serde_json::to_value(&method).unwrap();
5736 assert_eq!(
5737 json,
5738 json!({
5739 "id": "default-auth",
5740 "name": "Default Auth"
5741 })
5742 );
5743 assert!(!json.as_object().unwrap().contains_key("description"));
5745 assert!(!json.as_object().unwrap().contains_key("type"));
5747
5748 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5749 match deserialized {
5750 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5751 assert_eq!(id.0.as_ref(), "default-auth");
5752 assert_eq!(name, "Default Auth");
5753 }
5754 #[cfg(feature = "unstable_auth_methods")]
5755 _ => panic!("Expected Agent variant"),
5756 }
5757 }
5758
5759 #[test]
5760 fn test_auth_method_explicit_agent_deserialization() {
5761 let json = json!({
5763 "id": "agent-auth",
5764 "name": "Agent Auth",
5765 "type": "agent"
5766 });
5767
5768 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5769 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5770 }
5771
5772 #[test]
5773 fn test_session_delete_serialization() {
5774 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5775 assert_eq!(
5776 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5777 "session/delete"
5778 );
5779 assert_eq!(
5780 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5781 json!({
5782 "sessionId": "sess_abc123"
5783 })
5784 );
5785 assert_eq!(
5786 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5787 json!({})
5788 );
5789 assert_eq!(
5790 serde_json::to_value(
5791 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5792 )
5793 .unwrap(),
5794 json!({
5795 "delete": {}
5796 })
5797 );
5798 }
5799 #[test]
5800 fn test_session_additional_directories_serialization() {
5801 assert_eq!(
5802 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5803 json!({
5804 "cwd": "/home/user/project",
5805 "mcpServers": []
5806 })
5807 );
5808 assert_eq!(
5809 serde_json::to_value(
5810 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5811 PathBuf::from("/home/user/shared-lib"),
5812 PathBuf::from("/home/user/product-docs"),
5813 ])
5814 )
5815 .unwrap(),
5816 json!({
5817 "cwd": "/home/user/project",
5818 "additionalDirectories": [
5819 "/home/user/shared-lib",
5820 "/home/user/product-docs"
5821 ],
5822 "mcpServers": []
5823 })
5824 );
5825 assert_eq!(
5826 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5827 json!({
5828 "sessionId": "sess_abc123",
5829 "cwd": "/home/user/project"
5830 })
5831 );
5832 assert_eq!(
5833 serde_json::to_value(
5834 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5835 PathBuf::from("/home/user/shared-lib"),
5836 PathBuf::from("/home/user/product-docs"),
5837 ])
5838 )
5839 .unwrap(),
5840 json!({
5841 "sessionId": "sess_abc123",
5842 "cwd": "/home/user/project",
5843 "additionalDirectories": [
5844 "/home/user/shared-lib",
5845 "/home/user/product-docs"
5846 ]
5847 })
5848 );
5849 assert_eq!(
5850 serde_json::from_value::<SessionInfo>(json!({
5851 "sessionId": "sess_abc123",
5852 "cwd": "/home/user/project"
5853 }))
5854 .unwrap()
5855 .additional_directories,
5856 Vec::<PathBuf>::new()
5857 );
5858 }
5859 #[test]
5860 fn test_session_additional_directories_capabilities_serialization() {
5861 assert_eq!(
5862 serde_json::to_value(
5863 SessionCapabilities::new()
5864 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5865 )
5866 .unwrap(),
5867 json!({
5868 "additionalDirectories": {}
5869 })
5870 );
5871 }
5872
5873 #[cfg(feature = "unstable_auth_methods")]
5874 #[test]
5875 fn test_auth_method_env_var_serialization() {
5876 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5877 "api-key",
5878 "API Key",
5879 vec![AuthEnvVar::new("API_KEY")],
5880 ));
5881
5882 let json = serde_json::to_value(&method).unwrap();
5883 assert_eq!(
5884 json,
5885 json!({
5886 "id": "api-key",
5887 "name": "API Key",
5888 "type": "env_var",
5889 "vars": [{"name": "API_KEY"}]
5890 })
5891 );
5892 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5894 assert!(
5895 !json["vars"][0]
5896 .as_object()
5897 .unwrap()
5898 .contains_key("optional")
5899 );
5900
5901 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5902 match deserialized {
5903 AuthMethod::EnvVar(AuthMethodEnvVar {
5904 id,
5905 name: method_name,
5906 vars,
5907 link,
5908 ..
5909 }) => {
5910 assert_eq!(id.0.as_ref(), "api-key");
5911 assert_eq!(method_name, "API Key");
5912 assert_eq!(vars.len(), 1);
5913 assert_eq!(vars[0].name, "API_KEY");
5914 assert!(vars[0].secret);
5915 assert!(!vars[0].optional);
5916 assert!(link.is_none());
5917 }
5918 _ => panic!("Expected EnvVar variant"),
5919 }
5920 }
5921
5922 #[cfg(feature = "unstable_auth_methods")]
5923 #[test]
5924 fn test_auth_method_env_var_with_link_serialization() {
5925 let method = AuthMethod::EnvVar(
5926 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5927 .link("https://example.com/keys"),
5928 );
5929
5930 let json = serde_json::to_value(&method).unwrap();
5931 assert_eq!(
5932 json,
5933 json!({
5934 "id": "api-key",
5935 "name": "API Key",
5936 "type": "env_var",
5937 "vars": [{"name": "API_KEY"}],
5938 "link": "https://example.com/keys"
5939 })
5940 );
5941
5942 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5943 match deserialized {
5944 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5945 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5946 }
5947 _ => panic!("Expected EnvVar variant"),
5948 }
5949 }
5950
5951 #[cfg(feature = "unstable_auth_methods")]
5952 #[test]
5953 fn test_auth_method_env_var_multiple_vars() {
5954 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5955 "azure-openai",
5956 "Azure OpenAI",
5957 vec![
5958 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5959 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5960 .label("Endpoint URL")
5961 .secret(false),
5962 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5963 .label("API Version")
5964 .secret(false)
5965 .optional(true),
5966 ],
5967 ));
5968
5969 let json = serde_json::to_value(&method).unwrap();
5970 assert_eq!(
5971 json,
5972 json!({
5973 "id": "azure-openai",
5974 "name": "Azure OpenAI",
5975 "type": "env_var",
5976 "vars": [
5977 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5978 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5979 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5980 ]
5981 })
5982 );
5983
5984 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5985 match deserialized {
5986 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5987 assert_eq!(vars.len(), 3);
5988 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5990 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5991 assert!(vars[0].secret);
5992 assert!(!vars[0].optional);
5993 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5995 assert!(!vars[1].secret);
5996 assert!(!vars[1].optional);
5997 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5999 assert!(!vars[2].secret);
6000 assert!(vars[2].optional);
6001 }
6002 _ => panic!("Expected EnvVar variant"),
6003 }
6004 }
6005
6006 #[cfg(feature = "unstable_auth_methods")]
6007 #[test]
6008 fn test_auth_method_terminal_serialization() {
6009 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
6010
6011 let json = serde_json::to_value(&method).unwrap();
6012 assert_eq!(
6013 json,
6014 json!({
6015 "id": "tui-auth",
6016 "name": "Terminal Auth",
6017 "type": "terminal"
6018 })
6019 );
6020 assert!(!json.as_object().unwrap().contains_key("args"));
6022 assert!(!json.as_object().unwrap().contains_key("env"));
6023
6024 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
6025 match deserialized {
6026 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
6027 assert!(args.is_empty());
6028 assert!(env.is_empty());
6029 }
6030 _ => panic!("Expected Terminal variant"),
6031 }
6032 }
6033
6034 #[cfg(feature = "unstable_auth_methods")]
6035 #[test]
6036 fn test_auth_method_terminal_with_args_and_env_serialization() {
6037 use std::collections::HashMap;
6038
6039 let mut env = HashMap::new();
6040 env.insert("TERM".to_string(), "xterm-256color".to_string());
6041
6042 let method = AuthMethod::Terminal(
6043 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
6044 .args(vec!["--interactive".to_string(), "--color".to_string()])
6045 .env(env),
6046 );
6047
6048 let json = serde_json::to_value(&method).unwrap();
6049 assert_eq!(
6050 json,
6051 json!({
6052 "id": "tui-auth",
6053 "name": "Terminal Auth",
6054 "type": "terminal",
6055 "args": ["--interactive", "--color"],
6056 "env": {
6057 "TERM": "xterm-256color"
6058 }
6059 })
6060 );
6061
6062 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
6063 match deserialized {
6064 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
6065 assert_eq!(args, vec!["--interactive", "--color"]);
6066 assert_eq!(env.len(), 1);
6067 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
6068 }
6069 _ => panic!("Expected Terminal variant"),
6070 }
6071 }
6072
6073 #[cfg(feature = "unstable_boolean_config")]
6074 #[test]
6075 fn test_session_config_option_value_id_serialize() {
6076 let val = SessionConfigOptionValue::value_id("model-1");
6077 let json = serde_json::to_value(&val).unwrap();
6078 assert_eq!(json, json!({ "value": "model-1" }));
6080 assert!(!json.as_object().unwrap().contains_key("type"));
6081 }
6082
6083 #[cfg(feature = "unstable_boolean_config")]
6084 #[test]
6085 fn test_session_config_option_value_boolean_serialize() {
6086 let val = SessionConfigOptionValue::boolean(true);
6087 let json = serde_json::to_value(&val).unwrap();
6088 assert_eq!(json, json!({ "type": "boolean", "value": true }));
6089 }
6090
6091 #[cfg(feature = "unstable_boolean_config")]
6092 #[test]
6093 fn test_session_config_option_value_deserialize_no_type() {
6094 let json = json!({ "value": "model-1" });
6096 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6097 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
6098 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
6099 }
6100
6101 #[cfg(feature = "unstable_boolean_config")]
6102 #[test]
6103 fn test_session_config_option_value_deserialize_boolean() {
6104 let json = json!({ "type": "boolean", "value": true });
6105 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6106 assert_eq!(val, SessionConfigOptionValue::boolean(true));
6107 assert_eq!(val.as_bool(), Some(true));
6108 }
6109
6110 #[cfg(feature = "unstable_boolean_config")]
6111 #[test]
6112 fn test_session_config_option_value_deserialize_boolean_false() {
6113 let json = json!({ "type": "boolean", "value": false });
6114 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6115 assert_eq!(val, SessionConfigOptionValue::boolean(false));
6116 assert_eq!(val.as_bool(), Some(false));
6117 }
6118
6119 #[cfg(feature = "unstable_boolean_config")]
6120 #[test]
6121 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6122 let json = json!({ "type": "text", "value": "freeform input" });
6124 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6125 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6126 }
6127
6128 #[cfg(feature = "unstable_boolean_config")]
6129 #[test]
6130 fn test_session_config_option_value_roundtrip_value_id() {
6131 let original = SessionConfigOptionValue::value_id("option-a");
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 #[cfg(feature = "unstable_boolean_config")]
6138 #[test]
6139 fn test_session_config_option_value_roundtrip_boolean() {
6140 let original = SessionConfigOptionValue::boolean(false);
6141 let json = serde_json::to_value(&original).unwrap();
6142 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6143 assert_eq!(original, roundtripped);
6144 }
6145
6146 #[cfg(feature = "unstable_boolean_config")]
6147 #[test]
6148 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6149 let json = json!({ "type": "boolean", "value": "not a bool" });
6151 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6152 assert!(result.is_ok());
6154 assert_eq!(
6155 result.unwrap().as_value_id().unwrap().to_string(),
6156 "not a bool"
6157 );
6158 }
6159
6160 #[cfg(feature = "unstable_boolean_config")]
6161 #[test]
6162 fn test_session_config_option_value_from_impls() {
6163 let from_str: SessionConfigOptionValue = "model-1".into();
6164 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6165
6166 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6167 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6168
6169 let from_bool: SessionConfigOptionValue = true.into();
6170 assert_eq!(from_bool.as_bool(), Some(true));
6171 }
6172
6173 #[cfg(feature = "unstable_boolean_config")]
6174 #[test]
6175 fn test_set_session_config_option_request_value_id() {
6176 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6177 let json = serde_json::to_value(&req).unwrap();
6178 assert_eq!(
6179 json,
6180 json!({
6181 "sessionId": "sess_1",
6182 "configId": "model",
6183 "value": "model-1"
6184 })
6185 );
6186 assert!(!json.as_object().unwrap().contains_key("type"));
6188 }
6189
6190 #[cfg(feature = "unstable_boolean_config")]
6191 #[test]
6192 fn test_set_session_config_option_request_boolean() {
6193 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6194 let json = serde_json::to_value(&req).unwrap();
6195 assert_eq!(
6196 json,
6197 json!({
6198 "sessionId": "sess_1",
6199 "configId": "brave_mode",
6200 "type": "boolean",
6201 "value": true
6202 })
6203 );
6204 }
6205
6206 #[cfg(feature = "unstable_boolean_config")]
6207 #[test]
6208 fn test_set_session_config_option_request_deserialize_no_type() {
6209 let json = json!({
6211 "sessionId": "sess_1",
6212 "configId": "model",
6213 "value": "model-1"
6214 });
6215 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6216 assert_eq!(req.session_id.to_string(), "sess_1");
6217 assert_eq!(req.config_id.to_string(), "model");
6218 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6219 }
6220
6221 #[cfg(feature = "unstable_boolean_config")]
6222 #[test]
6223 fn test_set_session_config_option_request_deserialize_boolean() {
6224 let json = json!({
6225 "sessionId": "sess_1",
6226 "configId": "brave_mode",
6227 "type": "boolean",
6228 "value": true
6229 });
6230 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6231 assert_eq!(req.value.as_bool(), Some(true));
6232 }
6233
6234 #[cfg(feature = "unstable_boolean_config")]
6235 #[test]
6236 fn test_set_session_config_option_request_roundtrip_value_id() {
6237 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6238 let json = serde_json::to_value(&original).unwrap();
6239 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6240 assert_eq!(original, roundtripped);
6241 }
6242
6243 #[cfg(feature = "unstable_boolean_config")]
6244 #[test]
6245 fn test_set_session_config_option_request_roundtrip_boolean() {
6246 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6247 let json = serde_json::to_value(&original).unwrap();
6248 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6249 assert_eq!(original, roundtripped);
6250 }
6251
6252 #[cfg(feature = "unstable_boolean_config")]
6253 #[test]
6254 fn test_session_config_boolean_serialization() {
6255 let cfg = SessionConfigBoolean::new(true);
6256 let json = serde_json::to_value(&cfg).unwrap();
6257 assert_eq!(json, json!({ "currentValue": true }));
6258
6259 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6260 assert!(deserialized.current_value);
6261 }
6262
6263 #[cfg(feature = "unstable_boolean_config")]
6264 #[test]
6265 fn test_session_config_option_boolean_variant() {
6266 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6267 .description("Skip confirmation prompts")
6268 .meta(test_meta());
6269 assert_eq!(serialized_meta_key_count(&opt), 1);
6270
6271 let json = serde_json::to_value(&opt).unwrap();
6272 assert_eq!(
6273 json,
6274 json!({
6275 "id": "brave_mode",
6276 "name": "Brave Mode",
6277 "description": "Skip confirmation prompts",
6278 "type": "boolean",
6279 "currentValue": false,
6280 "_meta": {
6281 "source": "test"
6282 }
6283 })
6284 );
6285
6286 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6287 assert_eq!(deserialized.id.to_string(), "brave_mode");
6288 assert_eq!(deserialized.name, "Brave Mode");
6289 match deserialized.kind {
6290 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6291 _ => panic!("Expected Boolean kind"),
6292 }
6293 }
6294
6295 #[cfg(feature = "unstable_boolean_config")]
6296 #[test]
6297 fn test_session_config_option_select_still_works() {
6298 let opt = SessionConfigOption::select(
6300 "model",
6301 "Model",
6302 "model-1",
6303 vec![
6304 SessionConfigSelectOption::new("model-1", "Model 1"),
6305 SessionConfigSelectOption::new("model-2", "Model 2"),
6306 ],
6307 )
6308 .meta(test_meta());
6309 assert_eq!(serialized_meta_key_count(&opt), 1);
6310
6311 let json = serde_json::to_value(&opt).unwrap();
6312 assert_eq!(json["type"], "select");
6313 assert_eq!(json["currentValue"], "model-1");
6314 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6315 assert_eq!(json["_meta"]["source"], "test");
6316
6317 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6318 match deserialized.kind {
6319 SessionConfigKind::Select(ref s) => {
6320 assert_eq!(s.current_value.to_string(), "model-1");
6321 }
6322 _ => panic!("Expected Select kind"),
6323 }
6324 }
6325
6326 #[cfg(feature = "unstable_llm_providers")]
6327 #[test]
6328 fn test_llm_protocol_known_variants() {
6329 assert_eq!(
6330 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6331 json!("anthropic")
6332 );
6333 assert_eq!(
6334 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6335 json!("openai")
6336 );
6337 assert_eq!(
6338 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6339 json!("azure")
6340 );
6341 assert_eq!(
6342 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6343 json!("vertex")
6344 );
6345 assert_eq!(
6346 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6347 json!("bedrock")
6348 );
6349
6350 assert_eq!(
6351 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6352 LlmProtocol::Anthropic
6353 );
6354 assert_eq!(
6355 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6356 LlmProtocol::OpenAi
6357 );
6358 assert_eq!(
6359 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6360 LlmProtocol::Azure
6361 );
6362 assert_eq!(
6363 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6364 LlmProtocol::Vertex
6365 );
6366 assert_eq!(
6367 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6368 LlmProtocol::Bedrock
6369 );
6370 }
6371
6372 #[cfg(feature = "unstable_llm_providers")]
6373 #[test]
6374 fn test_llm_protocol_unknown_variant() {
6375 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6376 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6377
6378 let json = serde_json::to_value(&unknown).unwrap();
6379 assert_eq!(json, json!("cohere"));
6380 }
6381
6382 #[cfg(feature = "unstable_llm_providers")]
6383 #[test]
6384 fn test_provider_current_config_serialization() {
6385 let config =
6386 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6387
6388 let json = serde_json::to_value(&config).unwrap();
6389 assert_eq!(
6390 json,
6391 json!({
6392 "apiType": "anthropic",
6393 "baseUrl": "https://api.anthropic.com"
6394 })
6395 );
6396
6397 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6398 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6399 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6400 }
6401
6402 #[cfg(feature = "unstable_llm_providers")]
6403 #[test]
6404 fn test_provider_info_with_current_config() {
6405 let info = ProviderInfo::new(
6406 "main",
6407 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6408 true,
6409 Some(ProviderCurrentConfig::new(
6410 LlmProtocol::Anthropic,
6411 "https://api.anthropic.com",
6412 )),
6413 );
6414
6415 let json = serde_json::to_value(&info).unwrap();
6416 assert_eq!(
6417 json,
6418 json!({
6419 "id": "main",
6420 "supported": ["anthropic", "openai"],
6421 "required": true,
6422 "current": {
6423 "apiType": "anthropic",
6424 "baseUrl": "https://api.anthropic.com"
6425 }
6426 })
6427 );
6428
6429 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6430 assert_eq!(deserialized.id, "main");
6431 assert_eq!(deserialized.supported.len(), 2);
6432 assert!(deserialized.required);
6433 assert!(deserialized.current.is_some());
6434 assert_eq!(
6435 deserialized.current.as_ref().unwrap().api_type,
6436 LlmProtocol::Anthropic
6437 );
6438 }
6439
6440 #[cfg(feature = "unstable_llm_providers")]
6441 #[test]
6442 fn test_provider_info_disabled() {
6443 let info = ProviderInfo::new(
6444 "secondary",
6445 vec![LlmProtocol::OpenAi],
6446 false,
6447 None::<ProviderCurrentConfig>,
6448 );
6449
6450 let json = serde_json::to_value(&info).unwrap();
6451 assert_eq!(
6452 json,
6453 json!({
6454 "id": "secondary",
6455 "supported": ["openai"],
6456 "required": false
6457 })
6458 );
6459
6460 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6461 assert_eq!(deserialized.id, "secondary");
6462 assert!(!deserialized.required);
6463 assert!(deserialized.current.is_none());
6464 }
6465
6466 #[cfg(feature = "unstable_llm_providers")]
6467 #[test]
6468 fn test_provider_info_missing_current_defaults_to_none() {
6469 let json = json!({
6471 "id": "main",
6472 "supported": ["anthropic"],
6473 "required": true
6474 });
6475 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6476 assert!(deserialized.current.is_none());
6477 }
6478
6479 #[cfg(feature = "unstable_llm_providers")]
6480 #[test]
6481 fn test_provider_info_explicit_null_current_decodes_to_none() {
6482 let json = json!({
6486 "id": "main",
6487 "supported": ["anthropic"],
6488 "required": true,
6489 "current": null
6490 });
6491 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6492 assert!(deserialized.current.is_none());
6493 }
6494
6495 #[cfg(feature = "unstable_llm_providers")]
6496 #[test]
6497 fn test_list_providers_response_serialization() {
6498 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6499 "main",
6500 vec![LlmProtocol::Anthropic],
6501 true,
6502 Some(ProviderCurrentConfig::new(
6503 LlmProtocol::Anthropic,
6504 "https://api.anthropic.com",
6505 )),
6506 )]);
6507
6508 let json = serde_json::to_value(&response).unwrap();
6509 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6510 assert_eq!(json["providers"][0]["id"], "main");
6511
6512 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6513 assert_eq!(deserialized.providers.len(), 1);
6514 }
6515
6516 #[cfg(feature = "unstable_llm_providers")]
6517 #[test]
6518 fn test_set_provider_request_serialization() {
6519 use std::collections::HashMap;
6520
6521 let mut headers = HashMap::new();
6522 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6523
6524 let request =
6525 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6526 .headers(headers);
6527
6528 let json = serde_json::to_value(&request).unwrap();
6529 assert_eq!(
6530 json,
6531 json!({
6532 "id": "main",
6533 "apiType": "openai",
6534 "baseUrl": "https://api.openai.com/v1",
6535 "headers": {
6536 "Authorization": "Bearer sk-test"
6537 }
6538 })
6539 );
6540
6541 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6542 assert_eq!(deserialized.id, "main");
6543 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6544 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6545 assert_eq!(deserialized.headers.len(), 1);
6546 assert_eq!(
6547 deserialized.headers.get("Authorization").unwrap(),
6548 "Bearer sk-test"
6549 );
6550 }
6551
6552 #[cfg(feature = "unstable_llm_providers")]
6553 #[test]
6554 fn test_set_provider_request_omits_empty_headers() {
6555 let request =
6556 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6557
6558 let json = serde_json::to_value(&request).unwrap();
6559 assert!(!json.as_object().unwrap().contains_key("headers"));
6561 }
6562
6563 #[cfg(feature = "unstable_llm_providers")]
6564 #[test]
6565 fn test_disable_provider_request_serialization() {
6566 let request = DisableProviderRequest::new("secondary");
6567
6568 let json = serde_json::to_value(&request).unwrap();
6569 assert_eq!(json, json!({ "id": "secondary" }));
6570
6571 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6572 assert_eq!(deserialized.id, "secondary");
6573 }
6574
6575 #[cfg(feature = "unstable_llm_providers")]
6576 #[test]
6577 fn test_providers_capabilities_serialization() {
6578 let caps = ProvidersCapabilities::new();
6579
6580 let json = serde_json::to_value(&caps).unwrap();
6581 assert_eq!(json, json!({}));
6582
6583 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6584 assert!(deserialized.meta.is_none());
6585 }
6586
6587 #[cfg(feature = "unstable_llm_providers")]
6588 #[test]
6589 fn test_agent_capabilities_with_providers() {
6590 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6591
6592 let json = serde_json::to_value(&caps).unwrap();
6593 assert_eq!(json["providers"], json!({}));
6594
6595 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6596 assert!(deserialized.providers.is_some());
6597 }
6598}