1use std::{path::PathBuf, sync::Arc};
7
8use std::collections::HashMap;
9
10use derive_more::{Display, From};
11use serde::{Deserialize, Serialize};
12use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
13
14use crate::{IntoOption, ProtocolVersion, SkipListener};
15
16use super::{
17 ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, Meta, SessionId,
18};
19
20#[cfg(feature = "unstable_mcp_over_acp")]
21use super::mcp::{
22 MCP_MESSAGE_METHOD_NAME, MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
23};
24
25#[cfg(feature = "unstable_nes")]
26use super::{
27 AcceptNesNotification, CloseNesRequest, CloseNesResponse, DidChangeDocumentNotification,
28 DidCloseDocumentNotification, DidFocusDocumentNotification, DidOpenDocumentNotification,
29 DidSaveDocumentNotification, NesCapabilities, PositionEncodingKind, RejectNesNotification,
30 StartNesRequest, StartNesResponse, SuggestNesRequest, SuggestNesResponse,
31};
32
33#[cfg(feature = "unstable_nes")]
34use super::{
35 DOCUMENT_DID_CHANGE_METHOD_NAME, DOCUMENT_DID_CLOSE_METHOD_NAME,
36 DOCUMENT_DID_FOCUS_METHOD_NAME, DOCUMENT_DID_OPEN_METHOD_NAME, DOCUMENT_DID_SAVE_METHOD_NAME,
37 NES_ACCEPT_METHOD_NAME, NES_CLOSE_METHOD_NAME, NES_REJECT_METHOD_NAME, NES_START_METHOD_NAME,
38 NES_SUGGEST_METHOD_NAME,
39};
40
41#[serde_as]
49#[skip_serializing_none]
50#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
52#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME)))]
53#[serde(rename_all = "camelCase")]
54#[non_exhaustive]
55pub struct InitializeRequest {
56 pub protocol_version: ProtocolVersion,
58 #[serde_as(deserialize_as = "DefaultOnError")]
60 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
61 #[serde(default)]
62 pub client_capabilities: ClientCapabilities,
63 #[serde_as(deserialize_as = "DefaultOnError")]
67 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
68 #[serde(default)]
69 pub client_info: Option<Implementation>,
70 #[serde_as(deserialize_as = "DefaultOnError")]
76 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
77 #[serde(default)]
78 #[serde(rename = "_meta")]
79 pub meta: Option<Meta>,
80}
81
82impl InitializeRequest {
83 #[must_use]
85 pub fn new(protocol_version: ProtocolVersion) -> Self {
86 Self {
87 protocol_version,
88 client_capabilities: ClientCapabilities::default(),
89 client_info: None,
90 meta: None,
91 }
92 }
93
94 #[must_use]
96 pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
97 self.client_capabilities = client_capabilities;
98 self
99 }
100
101 #[must_use]
103 pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
104 self.client_info = client_info.into_option();
105 self
106 }
107
108 #[must_use]
114 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
115 self.meta = meta.into_option();
116 self
117 }
118}
119
120#[serde_as]
126#[skip_serializing_none]
127#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
128#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
129#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME)))]
130#[serde(rename_all = "camelCase")]
131#[non_exhaustive]
132pub struct InitializeResponse {
133 pub protocol_version: ProtocolVersion,
138 #[serde_as(deserialize_as = "DefaultOnError")]
140 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
141 #[serde(default)]
142 pub agent_capabilities: AgentCapabilities,
143 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
145 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
146 #[serde(default)]
147 pub auth_methods: Vec<AuthMethod>,
148 #[serde_as(deserialize_as = "DefaultOnError")]
152 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
153 #[serde(default)]
154 pub agent_info: Option<Implementation>,
155 #[serde_as(deserialize_as = "DefaultOnError")]
161 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
162 #[serde(default)]
163 #[serde(rename = "_meta")]
164 pub meta: Option<Meta>,
165}
166
167impl InitializeResponse {
168 #[must_use]
170 pub fn new(protocol_version: ProtocolVersion) -> Self {
171 Self {
172 protocol_version,
173 agent_capabilities: AgentCapabilities::default(),
174 auth_methods: vec![],
175 agent_info: None,
176 meta: None,
177 }
178 }
179
180 #[must_use]
182 pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
183 self.agent_capabilities = agent_capabilities;
184 self
185 }
186
187 #[must_use]
189 pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
190 self.auth_methods = auth_methods;
191 self
192 }
193
194 #[must_use]
196 pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
197 self.agent_info = agent_info.into_option();
198 self
199 }
200
201 #[must_use]
207 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
208 self.meta = meta.into_option();
209 self
210 }
211}
212
213#[serde_as]
217#[skip_serializing_none]
218#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
219#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
220#[serde(rename_all = "camelCase")]
221#[non_exhaustive]
222pub struct Implementation {
223 pub name: String,
226 #[serde_as(deserialize_as = "DefaultOnError")]
231 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
232 #[serde(default)]
233 pub title: Option<String>,
234 pub version: String,
237 #[serde_as(deserialize_as = "DefaultOnError")]
243 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
244 #[serde(default)]
245 #[serde(rename = "_meta")]
246 pub meta: Option<Meta>,
247}
248
249impl Implementation {
250 #[must_use]
252 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
253 Self {
254 name: name.into(),
255 title: None,
256 version: version.into(),
257 meta: None,
258 }
259 }
260
261 #[must_use]
266 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
267 self.title = title.into_option();
268 self
269 }
270
271 #[must_use]
277 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
278 self.meta = meta.into_option();
279 self
280 }
281}
282
283#[serde_as]
289#[skip_serializing_none]
290#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
291#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
292#[cfg_attr(feature = "schemars", 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 #[cfg_attr(feature = "schemars", 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
333crate::serde_util::default_on_null! {
334 #[serde_as]
336 #[skip_serializing_none]
337 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
338 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
339 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
340 #[serde(rename_all = "camelCase")]
341 #[non_exhaustive]
342 pub struct AuthenticateResponse {
343 #[serde_as(deserialize_as = "DefaultOnError")]
349 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
350 #[serde(default)]
351 #[serde(rename = "_meta")]
352 pub meta: Option<Meta>,
353 }
354}
355
356impl AuthenticateResponse {
357 #[must_use]
359 pub fn new() -> Self {
360 Self::default()
361 }
362
363 #[must_use]
369 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
370 self.meta = meta.into_option();
371 self
372 }
373}
374
375crate::serde_util::default_on_null! {
378 #[serde_as]
382 #[skip_serializing_none]
383 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
384 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
385 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
386 #[serde(rename_all = "camelCase")]
387 #[non_exhaustive]
388 pub struct LogoutRequest {
389 #[serde_as(deserialize_as = "DefaultOnError")]
395 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
396 #[serde(default)]
397 #[serde(rename = "_meta")]
398 pub meta: Option<Meta>,
399 }
400}
401
402impl LogoutRequest {
403 #[must_use]
405 pub fn new() -> Self {
406 Self::default()
407 }
408
409 #[must_use]
415 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
416 self.meta = meta.into_option();
417 self
418 }
419}
420
421crate::serde_util::default_on_null! {
422 #[serde_as]
424 #[skip_serializing_none]
425 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
426 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
427 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
428 #[serde(rename_all = "camelCase")]
429 #[non_exhaustive]
430 pub struct LogoutResponse {
431 #[serde_as(deserialize_as = "DefaultOnError")]
437 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
438 #[serde(default)]
439 #[serde(rename = "_meta")]
440 pub meta: Option<Meta>,
441 }
442}
443
444impl LogoutResponse {
445 #[must_use]
447 pub fn new() -> Self {
448 Self::default()
449 }
450
451 #[must_use]
457 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
458 self.meta = meta.into_option();
459 self
460 }
461}
462
463#[serde_as]
465#[skip_serializing_none]
466#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
467#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
468#[serde(rename_all = "camelCase")]
469#[non_exhaustive]
470pub struct AgentAuthCapabilities {
471 #[serde_as(deserialize_as = "DefaultOnError")]
476 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
477 #[serde(default)]
478 pub logout: Option<LogoutCapabilities>,
479 #[serde_as(deserialize_as = "DefaultOnError")]
485 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
486 #[serde(default)]
487 #[serde(rename = "_meta")]
488 pub meta: Option<Meta>,
489}
490
491impl AgentAuthCapabilities {
492 #[must_use]
494 pub fn new() -> Self {
495 Self::default()
496 }
497
498 #[must_use]
500 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
501 self.logout = logout.into_option();
502 self
503 }
504
505 #[must_use]
511 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
512 self.meta = meta.into_option();
513 self
514 }
515}
516
517#[serde_as]
521#[skip_serializing_none]
522#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
523#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
524#[non_exhaustive]
525pub struct LogoutCapabilities {
526 #[serde_as(deserialize_as = "DefaultOnError")]
532 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
533 #[serde(default)]
534 #[serde(rename = "_meta")]
535 pub meta: Option<Meta>,
536}
537
538impl LogoutCapabilities {
539 #[must_use]
541 pub fn new() -> Self {
542 Self::default()
543 }
544
545 #[must_use]
551 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
552 self.meta = meta.into_option();
553 self
554 }
555}
556
557#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
559#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
560#[serde(transparent)]
561#[from(Arc<str>, String, &'static str)]
562#[non_exhaustive]
563pub struct AuthMethodId(pub Arc<str>);
564
565impl AuthMethodId {
566 #[must_use]
568 pub fn new(id: impl Into<Arc<str>>) -> Self {
569 Self(id.into())
570 }
571}
572
573#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
578#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
579#[serde(tag = "type", rename_all = "snake_case")]
580#[non_exhaustive]
581pub enum AuthMethod {
582 Terminal(AuthMethodTerminal),
585 #[serde(untagged)]
589 Agent(AuthMethodAgent),
590}
591
592impl AuthMethod {
593 #[must_use]
595 pub fn id(&self) -> &AuthMethodId {
596 match self {
597 Self::Agent(a) => &a.id,
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 Self::Terminal(t) => &t.name,
608 }
609 }
610
611 #[must_use]
613 pub fn description(&self) -> Option<&str> {
614 match self {
615 Self::Agent(a) => a.description.as_deref(),
616 Self::Terminal(t) => t.description.as_deref(),
617 }
618 }
619
620 #[must_use]
626 pub fn meta(&self) -> Option<&Meta> {
627 match self {
628 Self::Agent(a) => a.meta.as_ref(),
629 Self::Terminal(t) => t.meta.as_ref(),
630 }
631 }
632}
633
634#[serde_as]
638#[skip_serializing_none]
639#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
640#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
641#[serde(rename_all = "camelCase")]
642#[non_exhaustive]
643pub struct AuthMethodAgent {
644 pub id: AuthMethodId,
646 pub name: String,
648 #[serde_as(deserialize_as = "DefaultOnError")]
650 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
651 #[serde(default)]
652 pub description: Option<String>,
653 #[serde_as(deserialize_as = "DefaultOnError")]
659 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
660 #[serde(default)]
661 #[serde(rename = "_meta")]
662 pub meta: Option<Meta>,
663}
664
665impl AuthMethodAgent {
666 #[must_use]
668 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
669 Self {
670 id: id.into(),
671 name: name.into(),
672 description: None,
673 meta: None,
674 }
675 }
676
677 #[must_use]
679 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
680 self.description = description.into_option();
681 self
682 }
683
684 #[must_use]
690 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
691 self.meta = meta.into_option();
692 self
693 }
694}
695
696#[serde_as]
704#[skip_serializing_none]
705#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
706#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
707#[serde(rename_all = "camelCase")]
708#[non_exhaustive]
709pub struct AuthMethodTerminal {
710 pub id: AuthMethodId,
712 pub name: String,
714 #[serde_as(deserialize_as = "DefaultOnError")]
716 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
717 #[serde(default)]
718 pub description: Option<String>,
719 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
721 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
722 #[serde(default, skip_serializing_if = "Vec::is_empty")]
723 pub args: Vec<String>,
724 #[serde_as(deserialize_as = "DefaultOnError")]
727 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
728 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
729 pub env: HashMap<String, String>,
730 #[serde_as(deserialize_as = "DefaultOnError")]
736 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
737 #[serde(default)]
738 #[serde(rename = "_meta")]
739 pub meta: Option<Meta>,
740}
741
742impl AuthMethodTerminal {
743 #[must_use]
745 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
746 Self {
747 id: id.into(),
748 name: name.into(),
749 description: None,
750 args: Vec::new(),
751 env: HashMap::new(),
752 meta: None,
753 }
754 }
755
756 #[must_use]
758 pub fn args(mut self, args: Vec<String>) -> Self {
759 self.args = args;
760 self
761 }
762
763 #[must_use]
766 pub fn env(mut self, env: HashMap<String, String>) -> Self {
767 self.env = env;
768 self
769 }
770
771 #[must_use]
773 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
774 self.description = description.into_option();
775 self
776 }
777
778 #[must_use]
784 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
785 self.meta = meta.into_option();
786 self
787 }
788}
789
790#[serde_as]
796#[skip_serializing_none]
797#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
798#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
799#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
800#[serde(rename_all = "camelCase")]
801#[non_exhaustive]
802pub struct NewSessionRequest {
803 pub cwd: PathBuf,
805 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
811 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
812 #[serde(default, skip_serializing_if = "Vec::is_empty")]
813 pub additional_directories: Vec<PathBuf>,
814 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
816 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
817 pub mcp_servers: Vec<McpServer>,
818 #[serde_as(deserialize_as = "DefaultOnError")]
824 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
825 #[serde(default)]
826 #[serde(rename = "_meta")]
827 pub meta: Option<Meta>,
828}
829
830impl NewSessionRequest {
831 #[must_use]
833 pub fn new(cwd: impl Into<PathBuf>) -> Self {
834 Self {
835 cwd: cwd.into(),
836 additional_directories: vec![],
837 mcp_servers: vec![],
838 meta: None,
839 }
840 }
841
842 #[must_use]
844 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
845 self.additional_directories = additional_directories;
846 self
847 }
848
849 #[must_use]
851 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
852 self.mcp_servers = mcp_servers;
853 self
854 }
855
856 #[must_use]
862 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
863 self.meta = meta.into_option();
864 self
865 }
866}
867
868#[serde_as]
872#[skip_serializing_none]
873#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
874#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
875#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
876#[serde(rename_all = "camelCase")]
877#[non_exhaustive]
878pub struct NewSessionResponse {
879 pub session_id: SessionId,
883 #[serde_as(deserialize_as = "DefaultOnError")]
887 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
888 #[serde(default)]
889 pub modes: Option<SessionModeState>,
890 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
892 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
893 #[serde(default)]
894 pub config_options: Option<Vec<SessionConfigOption>>,
895 #[serde_as(deserialize_as = "DefaultOnError")]
901 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
902 #[serde(default)]
903 #[serde(rename = "_meta")]
904 pub meta: Option<Meta>,
905}
906
907impl NewSessionResponse {
908 #[must_use]
910 pub fn new(session_id: impl Into<SessionId>) -> Self {
911 Self {
912 session_id: session_id.into(),
913 modes: None,
914 config_options: None,
915 meta: None,
916 }
917 }
918
919 #[must_use]
923 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
924 self.modes = modes.into_option();
925 self
926 }
927
928 #[must_use]
930 pub fn config_options(
931 mut self,
932 config_options: impl IntoOption<Vec<SessionConfigOption>>,
933 ) -> Self {
934 self.config_options = config_options.into_option();
935 self
936 }
937
938 #[must_use]
944 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
945 self.meta = meta.into_option();
946 self
947 }
948}
949
950#[serde_as]
958#[skip_serializing_none]
959#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
960#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
961#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
962#[serde(rename_all = "camelCase")]
963#[non_exhaustive]
964pub struct LoadSessionRequest {
965 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
967 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
968 pub mcp_servers: Vec<McpServer>,
969 pub cwd: PathBuf,
971 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
978 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
979 #[serde(default, skip_serializing_if = "Vec::is_empty")]
980 pub additional_directories: Vec<PathBuf>,
981 pub session_id: SessionId,
983 #[serde_as(deserialize_as = "DefaultOnError")]
989 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
990 #[serde(default)]
991 #[serde(rename = "_meta")]
992 pub meta: Option<Meta>,
993}
994
995impl LoadSessionRequest {
996 #[must_use]
998 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
999 Self {
1000 mcp_servers: vec![],
1001 cwd: cwd.into(),
1002 additional_directories: vec![],
1003 session_id: session_id.into(),
1004 meta: None,
1005 }
1006 }
1007
1008 #[must_use]
1010 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1011 self.additional_directories = additional_directories;
1012 self
1013 }
1014
1015 #[must_use]
1017 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1018 self.mcp_servers = mcp_servers;
1019 self
1020 }
1021
1022 #[must_use]
1028 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1029 self.meta = meta.into_option();
1030 self
1031 }
1032}
1033
1034crate::serde_util::default_on_null! {
1035 #[serde_as]
1037 #[skip_serializing_none]
1038 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1039 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1040 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1041 #[serde(rename_all = "camelCase")]
1042 #[non_exhaustive]
1043 pub struct LoadSessionResponse {
1044 #[serde_as(deserialize_as = "DefaultOnError")]
1048 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1049 #[serde(default)]
1050 pub modes: Option<SessionModeState>,
1051 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1053 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1054 #[serde(default)]
1055 pub config_options: Option<Vec<SessionConfigOption>>,
1056 #[serde_as(deserialize_as = "DefaultOnError")]
1062 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1063 #[serde(default)]
1064 #[serde(rename = "_meta")]
1065 pub meta: Option<Meta>,
1066 }
1067}
1068
1069impl LoadSessionResponse {
1070 #[must_use]
1072 pub fn new() -> Self {
1073 Self::default()
1074 }
1075
1076 #[must_use]
1080 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1081 self.modes = modes.into_option();
1082 self
1083 }
1084
1085 #[must_use]
1087 pub fn config_options(
1088 mut self,
1089 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1090 ) -> Self {
1091 self.config_options = config_options.into_option();
1092 self
1093 }
1094
1095 #[must_use]
1101 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1102 self.meta = meta.into_option();
1103 self
1104 }
1105}
1106
1107#[cfg(feature = "unstable_session_fork")]
1120#[serde_as]
1121#[skip_serializing_none]
1122#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1123#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1124#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1125#[serde(rename_all = "camelCase")]
1126#[non_exhaustive]
1127pub struct ForkSessionRequest {
1128 pub session_id: SessionId,
1130 pub cwd: PathBuf,
1132 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1138 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1139 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1140 pub additional_directories: Vec<PathBuf>,
1141 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1143 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1144 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1145 pub mcp_servers: Vec<McpServer>,
1146 #[serde_as(deserialize_as = "DefaultOnError")]
1152 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1153 #[serde(default)]
1154 #[serde(rename = "_meta")]
1155 pub meta: Option<Meta>,
1156}
1157
1158#[cfg(feature = "unstable_session_fork")]
1159impl ForkSessionRequest {
1160 #[must_use]
1162 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1163 Self {
1164 session_id: session_id.into(),
1165 cwd: cwd.into(),
1166 additional_directories: vec![],
1167 mcp_servers: vec![],
1168 meta: None,
1169 }
1170 }
1171
1172 #[must_use]
1174 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1175 self.additional_directories = additional_directories;
1176 self
1177 }
1178
1179 #[must_use]
1181 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1182 self.mcp_servers = mcp_servers;
1183 self
1184 }
1185
1186 #[must_use]
1192 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1193 self.meta = meta.into_option();
1194 self
1195 }
1196}
1197
1198#[cfg(feature = "unstable_session_fork")]
1204#[serde_as]
1205#[skip_serializing_none]
1206#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1207#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1208#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1209#[serde(rename_all = "camelCase")]
1210#[non_exhaustive]
1211pub struct ForkSessionResponse {
1212 pub session_id: SessionId,
1214 #[serde_as(deserialize_as = "DefaultOnError")]
1218 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1219 #[serde(default)]
1220 pub modes: Option<SessionModeState>,
1221 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1223 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1224 #[serde(default)]
1225 pub config_options: Option<Vec<SessionConfigOption>>,
1226 #[serde_as(deserialize_as = "DefaultOnError")]
1232 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1233 #[serde(default)]
1234 #[serde(rename = "_meta")]
1235 pub meta: Option<Meta>,
1236}
1237
1238#[cfg(feature = "unstable_session_fork")]
1239impl ForkSessionResponse {
1240 #[must_use]
1242 pub fn new(session_id: impl Into<SessionId>) -> Self {
1243 Self {
1244 session_id: session_id.into(),
1245 modes: None,
1246 config_options: None,
1247 meta: None,
1248 }
1249 }
1250
1251 #[must_use]
1255 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1256 self.modes = modes.into_option();
1257 self
1258 }
1259
1260 #[must_use]
1262 pub fn config_options(
1263 mut self,
1264 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1265 ) -> Self {
1266 self.config_options = config_options.into_option();
1267 self
1268 }
1269
1270 #[must_use]
1276 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1277 self.meta = meta.into_option();
1278 self
1279 }
1280}
1281
1282#[serde_as]
1291#[skip_serializing_none]
1292#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1293#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1294#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1295#[serde(rename_all = "camelCase")]
1296#[non_exhaustive]
1297pub struct ResumeSessionRequest {
1298 pub session_id: SessionId,
1300 pub cwd: PathBuf,
1302 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1309 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1310 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1311 pub additional_directories: Vec<PathBuf>,
1312 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1314 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1315 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1316 pub mcp_servers: Vec<McpServer>,
1317 #[serde_as(deserialize_as = "DefaultOnError")]
1323 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1324 #[serde(default)]
1325 #[serde(rename = "_meta")]
1326 pub meta: Option<Meta>,
1327}
1328
1329impl ResumeSessionRequest {
1330 #[must_use]
1332 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1333 Self {
1334 session_id: session_id.into(),
1335 cwd: cwd.into(),
1336 additional_directories: vec![],
1337 mcp_servers: vec![],
1338 meta: None,
1339 }
1340 }
1341
1342 #[must_use]
1344 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1345 self.additional_directories = additional_directories;
1346 self
1347 }
1348
1349 #[must_use]
1351 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1352 self.mcp_servers = mcp_servers;
1353 self
1354 }
1355
1356 #[must_use]
1362 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1363 self.meta = meta.into_option();
1364 self
1365 }
1366}
1367
1368crate::serde_util::default_on_null! {
1369 #[serde_as]
1371 #[skip_serializing_none]
1372 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1373 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1374 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1375 #[serde(rename_all = "camelCase")]
1376 #[non_exhaustive]
1377 pub struct ResumeSessionResponse {
1378 #[serde_as(deserialize_as = "DefaultOnError")]
1382 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1383 #[serde(default)]
1384 pub modes: Option<SessionModeState>,
1385 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1387 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1388 #[serde(default)]
1389 pub config_options: Option<Vec<SessionConfigOption>>,
1390 #[serde_as(deserialize_as = "DefaultOnError")]
1396 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1397 #[serde(default)]
1398 #[serde(rename = "_meta")]
1399 pub meta: Option<Meta>,
1400 }
1401}
1402
1403impl ResumeSessionResponse {
1404 #[must_use]
1406 pub fn new() -> Self {
1407 Self::default()
1408 }
1409
1410 #[must_use]
1414 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1415 self.modes = modes.into_option();
1416 self
1417 }
1418
1419 #[must_use]
1421 pub fn config_options(
1422 mut self,
1423 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1424 ) -> Self {
1425 self.config_options = config_options.into_option();
1426 self
1427 }
1428
1429 #[must_use]
1435 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1436 self.meta = meta.into_option();
1437 self
1438 }
1439}
1440
1441#[serde_as]
1451#[skip_serializing_none]
1452#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1453#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1454#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1455#[serde(rename_all = "camelCase")]
1456#[non_exhaustive]
1457pub struct CloseSessionRequest {
1458 pub session_id: SessionId,
1460 #[serde_as(deserialize_as = "DefaultOnError")]
1466 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1467 #[serde(default)]
1468 #[serde(rename = "_meta")]
1469 pub meta: Option<Meta>,
1470}
1471
1472impl CloseSessionRequest {
1473 #[must_use]
1475 pub fn new(session_id: impl Into<SessionId>) -> Self {
1476 Self {
1477 session_id: session_id.into(),
1478 meta: None,
1479 }
1480 }
1481
1482 #[must_use]
1488 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1489 self.meta = meta.into_option();
1490 self
1491 }
1492}
1493
1494crate::serde_util::default_on_null! {
1495 #[serde_as]
1497 #[skip_serializing_none]
1498 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1499 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1500 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1501 #[serde(rename_all = "camelCase")]
1502 #[non_exhaustive]
1503 pub struct CloseSessionResponse {
1504 #[serde_as(deserialize_as = "DefaultOnError")]
1510 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1511 #[serde(default)]
1512 #[serde(rename = "_meta")]
1513 pub meta: Option<Meta>,
1514 }
1515}
1516
1517impl CloseSessionResponse {
1518 #[must_use]
1520 pub fn new() -> Self {
1521 Self::default()
1522 }
1523
1524 #[must_use]
1530 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1531 self.meta = meta.into_option();
1532 self
1533 }
1534}
1535
1536crate::serde_util::default_on_null! {
1539 #[serde_as]
1543 #[skip_serializing_none]
1544 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1545 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1546 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
1547 #[serde(rename_all = "camelCase")]
1548 #[non_exhaustive]
1549 pub struct ListSessionsRequest {
1550 #[serde(default)]
1552 pub cwd: Option<PathBuf>,
1553 #[serde(default)]
1555 pub cursor: Option<String>,
1556 #[serde_as(deserialize_as = "DefaultOnError")]
1562 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1563 #[serde(default)]
1564 #[serde(rename = "_meta")]
1565 pub meta: Option<Meta>,
1566 }
1567}
1568
1569impl ListSessionsRequest {
1570 #[must_use]
1572 pub fn new() -> Self {
1573 Self::default()
1574 }
1575
1576 #[must_use]
1578 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1579 self.cwd = cwd.into_option();
1580 self
1581 }
1582
1583 #[must_use]
1585 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1586 self.cursor = cursor.into_option();
1587 self
1588 }
1589
1590 #[must_use]
1596 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1597 self.meta = meta.into_option();
1598 self
1599 }
1600}
1601
1602#[serde_as]
1604#[skip_serializing_none]
1605#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1606#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1607#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
1608#[serde(rename_all = "camelCase")]
1609#[non_exhaustive]
1610pub struct ListSessionsResponse {
1611 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1613 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1614 pub sessions: Vec<SessionInfo>,
1615 #[serde_as(deserialize_as = "DefaultOnError")]
1618 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1619 #[serde(default)]
1620 pub next_cursor: Option<String>,
1621 #[serde_as(deserialize_as = "DefaultOnError")]
1627 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1628 #[serde(default)]
1629 #[serde(rename = "_meta")]
1630 pub meta: Option<Meta>,
1631}
1632
1633impl ListSessionsResponse {
1634 #[must_use]
1636 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1637 Self {
1638 sessions,
1639 next_cursor: None,
1640 meta: None,
1641 }
1642 }
1643
1644 #[must_use]
1646 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1647 self.next_cursor = next_cursor.into_option();
1648 self
1649 }
1650
1651 #[must_use]
1657 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1658 self.meta = meta.into_option();
1659 self
1660 }
1661}
1662
1663#[serde_as]
1669#[skip_serializing_none]
1670#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1671#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1672#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
1673#[serde(rename_all = "camelCase")]
1674#[non_exhaustive]
1675pub struct DeleteSessionRequest {
1676 pub session_id: SessionId,
1678 #[serde_as(deserialize_as = "DefaultOnError")]
1684 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1685 #[serde(default)]
1686 #[serde(rename = "_meta")]
1687 pub meta: Option<Meta>,
1688}
1689
1690impl DeleteSessionRequest {
1691 #[must_use]
1693 pub fn new(session_id: impl Into<SessionId>) -> Self {
1694 Self {
1695 session_id: session_id.into(),
1696 meta: None,
1697 }
1698 }
1699
1700 #[must_use]
1706 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1707 self.meta = meta.into_option();
1708 self
1709 }
1710}
1711
1712crate::serde_util::default_on_null! {
1713 #[serde_as]
1715 #[skip_serializing_none]
1716 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1717 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1718 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
1719 #[serde(rename_all = "camelCase")]
1720 #[non_exhaustive]
1721 pub struct DeleteSessionResponse {
1722 #[serde_as(deserialize_as = "DefaultOnError")]
1728 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1729 #[serde(default)]
1730 #[serde(rename = "_meta")]
1731 pub meta: Option<Meta>,
1732 }
1733}
1734
1735impl DeleteSessionResponse {
1736 #[must_use]
1738 pub fn new() -> Self {
1739 Self::default()
1740 }
1741
1742 #[must_use]
1748 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1749 self.meta = meta.into_option();
1750 self
1751 }
1752}
1753
1754#[serde_as]
1756#[skip_serializing_none]
1757#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1758#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1759#[serde(rename_all = "camelCase")]
1760#[non_exhaustive]
1761pub struct SessionInfo {
1762 pub session_id: SessionId,
1764 pub cwd: PathBuf,
1766 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1772 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1773 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1774 pub additional_directories: Vec<PathBuf>,
1775
1776 #[serde_as(deserialize_as = "DefaultOnError")]
1778 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1779 #[serde(default)]
1780 pub title: Option<String>,
1781 #[serde_as(deserialize_as = "DefaultOnError")]
1783 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1784 #[serde(default)]
1785 pub updated_at: Option<String>,
1786 #[serde_as(deserialize_as = "DefaultOnError")]
1792 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1793 #[serde(default)]
1794 #[serde(rename = "_meta")]
1795 pub meta: Option<Meta>,
1796}
1797
1798impl SessionInfo {
1799 #[must_use]
1801 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1802 Self {
1803 session_id: session_id.into(),
1804 cwd: cwd.into(),
1805 additional_directories: vec![],
1806 title: None,
1807 updated_at: None,
1808 meta: None,
1809 }
1810 }
1811
1812 #[must_use]
1814 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1815 self.additional_directories = additional_directories;
1816 self
1817 }
1818
1819 #[must_use]
1821 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1822 self.title = title.into_option();
1823 self
1824 }
1825
1826 #[must_use]
1828 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1829 self.updated_at = updated_at.into_option();
1830 self
1831 }
1832
1833 #[must_use]
1839 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1840 self.meta = meta.into_option();
1841 self
1842 }
1843}
1844
1845#[serde_as]
1849#[skip_serializing_none]
1850#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1851#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1852#[serde(rename_all = "camelCase")]
1853#[non_exhaustive]
1854pub struct SessionModeState {
1855 pub current_mode_id: SessionModeId,
1857 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1859 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1860 pub available_modes: Vec<SessionMode>,
1861 #[serde_as(deserialize_as = "DefaultOnError")]
1867 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1868 #[serde(default)]
1869 #[serde(rename = "_meta")]
1870 pub meta: Option<Meta>,
1871}
1872
1873impl SessionModeState {
1874 #[must_use]
1876 pub fn new(
1877 current_mode_id: impl Into<SessionModeId>,
1878 available_modes: Vec<SessionMode>,
1879 ) -> Self {
1880 Self {
1881 current_mode_id: current_mode_id.into(),
1882 available_modes,
1883 meta: None,
1884 }
1885 }
1886
1887 #[must_use]
1893 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1894 self.meta = meta.into_option();
1895 self
1896 }
1897}
1898
1899#[serde_as]
1903#[skip_serializing_none]
1904#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1905#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1906#[serde(rename_all = "camelCase")]
1907#[non_exhaustive]
1908pub struct SessionMode {
1909 pub id: SessionModeId,
1911 pub name: String,
1913 #[serde_as(deserialize_as = "DefaultOnError")]
1915 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1916 #[serde(default)]
1917 pub description: Option<String>,
1918 #[serde_as(deserialize_as = "DefaultOnError")]
1924 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1925 #[serde(default)]
1926 #[serde(rename = "_meta")]
1927 pub meta: Option<Meta>,
1928}
1929
1930impl SessionMode {
1931 #[must_use]
1933 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
1934 Self {
1935 id: id.into(),
1936 name: name.into(),
1937 description: None,
1938 meta: None,
1939 }
1940 }
1941
1942 #[must_use]
1944 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1945 self.description = description.into_option();
1946 self
1947 }
1948
1949 #[must_use]
1955 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1956 self.meta = meta.into_option();
1957 self
1958 }
1959}
1960
1961#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1963#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
1964#[serde(transparent)]
1965#[from(Arc<str>, String, &'static str)]
1966#[non_exhaustive]
1967pub struct SessionModeId(pub Arc<str>);
1968
1969impl SessionModeId {
1970 #[must_use]
1972 pub fn new(id: impl Into<Arc<str>>) -> Self {
1973 Self(id.into())
1974 }
1975}
1976
1977#[serde_as]
1979#[skip_serializing_none]
1980#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1981#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1982#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
1983#[serde(rename_all = "camelCase")]
1984#[non_exhaustive]
1985pub struct SetSessionModeRequest {
1986 pub session_id: SessionId,
1988 pub mode_id: SessionModeId,
1990 #[serde_as(deserialize_as = "DefaultOnError")]
1996 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1997 #[serde(default)]
1998 #[serde(rename = "_meta")]
1999 pub meta: Option<Meta>,
2000}
2001
2002impl SetSessionModeRequest {
2003 #[must_use]
2005 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
2006 Self {
2007 session_id: session_id.into(),
2008 mode_id: mode_id.into(),
2009 meta: None,
2010 }
2011 }
2012
2013 #[must_use]
2015 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2016 self.meta = meta.into_option();
2017 self
2018 }
2019}
2020
2021crate::serde_util::default_on_null! {
2022 #[serde_as]
2024 #[skip_serializing_none]
2025 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2026 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
2027 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
2028 #[serde(rename_all = "camelCase")]
2029 #[non_exhaustive]
2030 pub struct SetSessionModeResponse {
2031 #[serde_as(deserialize_as = "DefaultOnError")]
2037 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2038 #[serde(default)]
2039 #[serde(rename = "_meta")]
2040 pub meta: Option<Meta>,
2041 }
2042}
2043
2044impl SetSessionModeResponse {
2045 #[must_use]
2047 pub fn new() -> Self {
2048 Self::default()
2049 }
2050
2051 #[must_use]
2057 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2058 self.meta = meta.into_option();
2059 self
2060 }
2061}
2062
2063#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2067#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2068#[serde(transparent)]
2069#[from(Arc<str>, String, &'static str)]
2070#[non_exhaustive]
2071pub struct SessionConfigId(pub Arc<str>);
2072
2073impl SessionConfigId {
2074 #[must_use]
2076 pub fn new(id: impl Into<Arc<str>>) -> Self {
2077 Self(id.into())
2078 }
2079}
2080
2081#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2083#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2084#[serde(transparent)]
2085#[from(Arc<str>, String, &'static str)]
2086#[non_exhaustive]
2087pub struct SessionConfigValueId(pub Arc<str>);
2088
2089impl SessionConfigValueId {
2090 #[must_use]
2092 pub fn new(id: impl Into<Arc<str>>) -> Self {
2093 Self(id.into())
2094 }
2095}
2096
2097#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2099#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2100#[serde(transparent)]
2101#[from(Arc<str>, String, &'static str)]
2102#[non_exhaustive]
2103pub struct SessionConfigGroupId(pub Arc<str>);
2104
2105impl SessionConfigGroupId {
2106 #[must_use]
2108 pub fn new(id: impl Into<Arc<str>>) -> Self {
2109 Self(id.into())
2110 }
2111}
2112
2113#[serde_as]
2115#[skip_serializing_none]
2116#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2118#[serde(rename_all = "camelCase")]
2119#[non_exhaustive]
2120pub struct SessionConfigSelectOption {
2121 pub value: SessionConfigValueId,
2123 pub name: String,
2125 #[serde_as(deserialize_as = "DefaultOnError")]
2127 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2128 #[serde(default)]
2129 pub description: Option<String>,
2130 #[serde_as(deserialize_as = "DefaultOnError")]
2136 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2137 #[serde(default)]
2138 #[serde(rename = "_meta")]
2139 pub meta: Option<Meta>,
2140}
2141
2142impl SessionConfigSelectOption {
2143 #[must_use]
2145 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2146 Self {
2147 value: value.into(),
2148 name: name.into(),
2149 description: None,
2150 meta: None,
2151 }
2152 }
2153
2154 #[must_use]
2156 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2157 self.description = description.into_option();
2158 self
2159 }
2160
2161 #[must_use]
2167 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2168 self.meta = meta.into_option();
2169 self
2170 }
2171}
2172
2173#[serde_as]
2175#[skip_serializing_none]
2176#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2177#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2178#[serde(rename_all = "camelCase")]
2179#[non_exhaustive]
2180pub struct SessionConfigSelectGroup {
2181 pub group: SessionConfigGroupId,
2183 pub name: String,
2185 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2187 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2188 pub options: Vec<SessionConfigSelectOption>,
2189 #[serde_as(deserialize_as = "DefaultOnError")]
2195 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2196 #[serde(default)]
2197 #[serde(rename = "_meta")]
2198 pub meta: Option<Meta>,
2199}
2200
2201impl SessionConfigSelectGroup {
2202 #[must_use]
2204 pub fn new(
2205 group: impl Into<SessionConfigGroupId>,
2206 name: impl Into<String>,
2207 options: Vec<SessionConfigSelectOption>,
2208 ) -> Self {
2209 Self {
2210 group: group.into(),
2211 name: name.into(),
2212 options,
2213 meta: None,
2214 }
2215 }
2216
2217 #[must_use]
2223 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2224 self.meta = meta.into_option();
2225 self
2226 }
2227}
2228
2229#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2231#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2232#[serde(untagged)]
2233#[non_exhaustive]
2234pub enum SessionConfigSelectOptions {
2235 Ungrouped(Vec<SessionConfigSelectOption>),
2237 Grouped(Vec<SessionConfigSelectGroup>),
2239}
2240
2241impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2242 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2243 SessionConfigSelectOptions::Ungrouped(options)
2244 }
2245}
2246
2247impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2248 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2249 SessionConfigSelectOptions::Grouped(groups)
2250 }
2251}
2252
2253#[skip_serializing_none]
2255#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2256#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2257#[serde(rename_all = "camelCase")]
2258#[non_exhaustive]
2259pub struct SessionConfigSelect {
2260 pub current_value: SessionConfigValueId,
2262 pub options: SessionConfigSelectOptions,
2264}
2265
2266impl SessionConfigSelect {
2267 #[must_use]
2269 pub fn new(
2270 current_value: impl Into<SessionConfigValueId>,
2271 options: impl Into<SessionConfigSelectOptions>,
2272 ) -> Self {
2273 Self {
2274 current_value: current_value.into(),
2275 options: options.into(),
2276 }
2277 }
2278}
2279
2280#[skip_serializing_none]
2282#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2283#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2284#[serde(rename_all = "camelCase")]
2285#[non_exhaustive]
2286pub struct SessionConfigBoolean {
2287 pub current_value: bool,
2289}
2290
2291impl SessionConfigBoolean {
2292 #[must_use]
2294 pub fn new(current_value: bool) -> Self {
2295 Self { current_value }
2296 }
2297}
2298
2299#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2309#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2310#[serde(rename_all = "snake_case")]
2311#[non_exhaustive]
2312pub enum SessionConfigOptionCategory {
2313 Mode,
2315 Model,
2317 ModelConfig,
2319 ThoughtLevel,
2321 #[serde(untagged)]
2323 Other(String),
2324}
2325
2326#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2328#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2329#[serde(tag = "type", rename_all = "snake_case")]
2330#[cfg_attr(feature = "schemars", schemars(extend("discriminator" = {"propertyName": "type"})))]
2331#[non_exhaustive]
2332pub enum SessionConfigKind {
2333 Select(SessionConfigSelect),
2335 Boolean(SessionConfigBoolean),
2337}
2338
2339#[serde_as]
2341#[skip_serializing_none]
2342#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2343#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2344#[serde(rename_all = "camelCase")]
2345#[non_exhaustive]
2346pub struct SessionConfigOption {
2347 pub id: SessionConfigId,
2349 pub name: String,
2351 #[serde_as(deserialize_as = "DefaultOnError")]
2353 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2354 #[serde(default)]
2355 pub description: Option<String>,
2356 #[serde_as(deserialize_as = "DefaultOnError")]
2358 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2359 #[serde(default)]
2360 pub category: Option<SessionConfigOptionCategory>,
2361 #[serde(flatten)]
2363 pub kind: SessionConfigKind,
2364 #[serde_as(deserialize_as = "DefaultOnError")]
2370 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2371 #[serde(default)]
2372 #[serde(rename = "_meta")]
2373 pub meta: Option<Meta>,
2374}
2375
2376impl SessionConfigOption {
2377 #[must_use]
2379 pub fn new(
2380 id: impl Into<SessionConfigId>,
2381 name: impl Into<String>,
2382 kind: SessionConfigKind,
2383 ) -> Self {
2384 Self {
2385 id: id.into(),
2386 name: name.into(),
2387 description: None,
2388 category: None,
2389 kind,
2390 meta: None,
2391 }
2392 }
2393
2394 #[must_use]
2396 pub fn select(
2397 id: impl Into<SessionConfigId>,
2398 name: impl Into<String>,
2399 current_value: impl Into<SessionConfigValueId>,
2400 options: impl Into<SessionConfigSelectOptions>,
2401 ) -> Self {
2402 Self::new(
2403 id,
2404 name,
2405 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2406 )
2407 }
2408
2409 #[must_use]
2411 pub fn boolean(
2412 id: impl Into<SessionConfigId>,
2413 name: impl Into<String>,
2414 current_value: bool,
2415 ) -> Self {
2416 Self::new(
2417 id,
2418 name,
2419 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2420 )
2421 }
2422
2423 #[must_use]
2425 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2426 self.description = description.into_option();
2427 self
2428 }
2429
2430 #[must_use]
2432 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2433 self.category = category.into_option();
2434 self
2435 }
2436
2437 #[must_use]
2443 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2444 self.meta = meta.into_option();
2445 self
2446 }
2447}
2448
2449#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2460#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2461#[serde(tag = "type", rename_all = "snake_case")]
2462#[non_exhaustive]
2463pub enum SessionConfigOptionValue {
2464 Boolean {
2466 value: bool,
2468 },
2469 #[serde(untagged)]
2475 ValueId {
2476 value: SessionConfigValueId,
2478 },
2479}
2480
2481impl SessionConfigOptionValue {
2482 #[must_use]
2484 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2485 Self::ValueId { value: id.into() }
2486 }
2487
2488 #[must_use]
2490 pub fn boolean(val: bool) -> Self {
2491 Self::Boolean { value: val }
2492 }
2493
2494 #[must_use]
2497 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2498 match self {
2499 Self::ValueId { value } => Some(value),
2500 _ => None,
2501 }
2502 }
2503
2504 #[must_use]
2506 pub fn as_bool(&self) -> Option<bool> {
2507 match self {
2508 Self::Boolean { value } => Some(*value),
2509 _ => None,
2510 }
2511 }
2512}
2513
2514impl From<SessionConfigValueId> for SessionConfigOptionValue {
2515 fn from(value: SessionConfigValueId) -> Self {
2516 Self::ValueId { value }
2517 }
2518}
2519
2520impl From<bool> for SessionConfigOptionValue {
2521 fn from(value: bool) -> Self {
2522 Self::Boolean { value }
2523 }
2524}
2525
2526impl From<&str> for SessionConfigOptionValue {
2527 fn from(value: &str) -> Self {
2528 Self::ValueId {
2529 value: SessionConfigValueId::new(value),
2530 }
2531 }
2532}
2533
2534#[serde_as]
2536#[skip_serializing_none]
2537#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2538#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2539#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
2540#[serde(rename_all = "camelCase")]
2541#[non_exhaustive]
2542pub struct SetSessionConfigOptionRequest {
2543 pub session_id: SessionId,
2545 pub config_id: SessionConfigId,
2547 #[serde(flatten)]
2552 pub value: SessionConfigOptionValue,
2553 #[serde_as(deserialize_as = "DefaultOnError")]
2559 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2560 #[serde(default)]
2561 #[serde(rename = "_meta")]
2562 pub meta: Option<Meta>,
2563}
2564
2565impl SetSessionConfigOptionRequest {
2566 #[must_use]
2568 pub fn new(
2569 session_id: impl Into<SessionId>,
2570 config_id: impl Into<SessionConfigId>,
2571 value: impl Into<SessionConfigOptionValue>,
2572 ) -> Self {
2573 Self {
2574 session_id: session_id.into(),
2575 config_id: config_id.into(),
2576 value: value.into(),
2577 meta: None,
2578 }
2579 }
2580
2581 #[must_use]
2587 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2588 self.meta = meta.into_option();
2589 self
2590 }
2591}
2592
2593#[serde_as]
2595#[skip_serializing_none]
2596#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2597#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2598#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
2599#[serde(rename_all = "camelCase")]
2600#[non_exhaustive]
2601pub struct SetSessionConfigOptionResponse {
2602 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2604 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2605 pub config_options: Vec<SessionConfigOption>,
2606 #[serde_as(deserialize_as = "DefaultOnError")]
2612 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2613 #[serde(default)]
2614 #[serde(rename = "_meta")]
2615 pub meta: Option<Meta>,
2616}
2617
2618impl SetSessionConfigOptionResponse {
2619 #[must_use]
2621 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2622 Self {
2623 config_options,
2624 meta: None,
2625 }
2626 }
2627
2628 #[must_use]
2634 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2635 self.meta = meta.into_option();
2636 self
2637 }
2638}
2639
2640#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2649#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2650#[serde(tag = "type", rename_all = "snake_case")]
2651#[non_exhaustive]
2652pub enum McpServer {
2653 Http(McpServerHttp),
2657 Sse(McpServerSse),
2661 #[cfg(feature = "unstable_mcp_over_acp")]
2670 Acp(McpServerAcp),
2671 #[serde(untagged)]
2675 Stdio(McpServerStdio),
2676}
2677
2678#[serde_as]
2680#[skip_serializing_none]
2681#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2682#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2683#[serde(rename_all = "camelCase")]
2684#[non_exhaustive]
2685pub struct McpServerHttp {
2686 pub name: String,
2688 pub url: String,
2690 pub headers: Vec<HttpHeader>,
2692 #[serde_as(deserialize_as = "DefaultOnError")]
2698 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2699 #[serde(default)]
2700 #[serde(rename = "_meta")]
2701 pub meta: Option<Meta>,
2702}
2703
2704impl McpServerHttp {
2705 #[must_use]
2707 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2708 Self {
2709 name: name.into(),
2710 url: url.into(),
2711 headers: Vec::new(),
2712 meta: None,
2713 }
2714 }
2715
2716 #[must_use]
2718 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2719 self.headers = headers;
2720 self
2721 }
2722
2723 #[must_use]
2729 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2730 self.meta = meta.into_option();
2731 self
2732 }
2733}
2734
2735#[serde_as]
2737#[skip_serializing_none]
2738#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2739#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2740#[serde(rename_all = "camelCase")]
2741#[non_exhaustive]
2742pub struct McpServerSse {
2743 pub name: String,
2745 pub url: String,
2747 pub headers: Vec<HttpHeader>,
2749 #[serde_as(deserialize_as = "DefaultOnError")]
2755 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2756 #[serde(default)]
2757 #[serde(rename = "_meta")]
2758 pub meta: Option<Meta>,
2759}
2760
2761impl McpServerSse {
2762 #[must_use]
2764 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2765 Self {
2766 name: name.into(),
2767 url: url.into(),
2768 headers: Vec::new(),
2769 meta: None,
2770 }
2771 }
2772
2773 #[must_use]
2775 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2776 self.headers = headers;
2777 self
2778 }
2779
2780 #[must_use]
2786 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2787 self.meta = meta.into_option();
2788 self
2789 }
2790}
2791
2792#[cfg(feature = "unstable_mcp_over_acp")]
2802#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2803#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
2804#[serde(transparent)]
2805#[from(Arc<str>, String, &'static str)]
2806#[non_exhaustive]
2807pub struct McpServerAcpId(pub Arc<str>);
2808
2809#[cfg(feature = "unstable_mcp_over_acp")]
2810impl McpServerAcpId {
2811 #[must_use]
2813 pub fn new(id: impl Into<Arc<str>>) -> Self {
2814 Self(id.into())
2815 }
2816}
2817
2818#[serde_as]
2827#[skip_serializing_none]
2828#[cfg(feature = "unstable_mcp_over_acp")]
2829#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2830#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2831#[serde(rename_all = "camelCase")]
2832#[non_exhaustive]
2833pub struct McpServerAcp {
2834 pub name: String,
2836 pub server_id: McpServerAcpId,
2841 #[serde_as(deserialize_as = "DefaultOnError")]
2847 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2848 #[serde(default)]
2849 #[serde(rename = "_meta")]
2850 pub meta: Option<Meta>,
2851}
2852
2853#[cfg(feature = "unstable_mcp_over_acp")]
2854impl McpServerAcp {
2855 #[must_use]
2857 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2858 Self {
2859 name: name.into(),
2860 server_id: id.into(),
2861 meta: None,
2862 }
2863 }
2864
2865 #[must_use]
2871 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2872 self.meta = meta.into_option();
2873 self
2874 }
2875}
2876
2877#[serde_as]
2879#[skip_serializing_none]
2880#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2881#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2882#[serde(rename_all = "camelCase")]
2883#[non_exhaustive]
2884pub struct McpServerStdio {
2885 pub name: String,
2887 pub command: PathBuf,
2889 pub args: Vec<String>,
2891 pub env: Vec<EnvVariable>,
2893 #[serde_as(deserialize_as = "DefaultOnError")]
2899 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2900 #[serde(default)]
2901 #[serde(rename = "_meta")]
2902 pub meta: Option<Meta>,
2903}
2904
2905impl McpServerStdio {
2906 #[must_use]
2908 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2909 Self {
2910 name: name.into(),
2911 command: command.into(),
2912 args: Vec::new(),
2913 env: Vec::new(),
2914 meta: None,
2915 }
2916 }
2917
2918 #[must_use]
2920 pub fn args(mut self, args: Vec<String>) -> Self {
2921 self.args = args;
2922 self
2923 }
2924
2925 #[must_use]
2927 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2928 self.env = env;
2929 self
2930 }
2931
2932 #[must_use]
2938 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2939 self.meta = meta.into_option();
2940 self
2941 }
2942}
2943
2944#[serde_as]
2946#[skip_serializing_none]
2947#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2948#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2949#[serde(rename_all = "camelCase")]
2950#[non_exhaustive]
2951pub struct EnvVariable {
2952 pub name: String,
2954 pub value: String,
2956 #[serde_as(deserialize_as = "DefaultOnError")]
2962 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2963 #[serde(default)]
2964 #[serde(rename = "_meta")]
2965 pub meta: Option<Meta>,
2966}
2967
2968impl EnvVariable {
2969 #[must_use]
2971 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2972 Self {
2973 name: name.into(),
2974 value: value.into(),
2975 meta: None,
2976 }
2977 }
2978
2979 #[must_use]
2985 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2986 self.meta = meta.into_option();
2987 self
2988 }
2989}
2990
2991#[serde_as]
2993#[skip_serializing_none]
2994#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2995#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2996#[serde(rename_all = "camelCase")]
2997#[non_exhaustive]
2998pub struct HttpHeader {
2999 pub name: String,
3001 pub value: String,
3003 #[serde_as(deserialize_as = "DefaultOnError")]
3009 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3010 #[serde(default)]
3011 #[serde(rename = "_meta")]
3012 pub meta: Option<Meta>,
3013}
3014
3015impl HttpHeader {
3016 #[must_use]
3018 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3019 Self {
3020 name: name.into(),
3021 value: value.into(),
3022 meta: None,
3023 }
3024 }
3025
3026 #[must_use]
3032 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3033 self.meta = meta.into_option();
3034 self
3035 }
3036}
3037
3038#[serde_as]
3046#[skip_serializing_none]
3047#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3048#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
3049#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
3050#[serde(rename_all = "camelCase")]
3051#[non_exhaustive]
3052pub struct PromptRequest {
3053 pub session_id: SessionId,
3055 pub prompt: Vec<ContentBlock>,
3069 #[serde_as(deserialize_as = "DefaultOnError")]
3075 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3076 #[serde(default)]
3077 #[serde(rename = "_meta")]
3078 pub meta: Option<Meta>,
3079}
3080
3081impl PromptRequest {
3082 #[must_use]
3084 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3085 Self {
3086 session_id: session_id.into(),
3087 prompt,
3088 meta: None,
3089 }
3090 }
3091
3092 #[must_use]
3098 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3099 self.meta = meta.into_option();
3100 self
3101 }
3102}
3103
3104#[serde_as]
3108#[skip_serializing_none]
3109#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3110#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3111#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
3112#[serde(rename_all = "camelCase")]
3113#[non_exhaustive]
3114pub struct PromptResponse {
3115 pub stop_reason: StopReason,
3117 #[cfg(feature = "unstable_end_turn_token_usage")]
3123 #[serde_as(deserialize_as = "DefaultOnError")]
3124 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3125 #[serde(default)]
3126 pub usage: Option<Usage>,
3127 #[serde_as(deserialize_as = "DefaultOnError")]
3133 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3134 #[serde(default)]
3135 #[serde(rename = "_meta")]
3136 pub meta: Option<Meta>,
3137}
3138
3139impl PromptResponse {
3140 #[must_use]
3142 pub fn new(stop_reason: StopReason) -> Self {
3143 Self {
3144 stop_reason,
3145 #[cfg(feature = "unstable_end_turn_token_usage")]
3146 usage: None,
3147 meta: None,
3148 }
3149 }
3150
3151 #[cfg(feature = "unstable_end_turn_token_usage")]
3157 #[must_use]
3158 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3159 self.usage = usage.into_option();
3160 self
3161 }
3162
3163 #[must_use]
3169 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3170 self.meta = meta.into_option();
3171 self
3172 }
3173}
3174
3175#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3179#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
3180#[serde(rename_all = "snake_case")]
3181#[non_exhaustive]
3182pub enum StopReason {
3183 EndTurn,
3185 MaxTokens,
3187 MaxTurnRequests,
3190 Refusal,
3194 Cancelled,
3201}
3202
3203#[cfg(feature = "unstable_end_turn_token_usage")]
3209#[serde_as]
3210#[skip_serializing_none]
3211#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3212#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3213#[serde(rename_all = "camelCase")]
3214#[non_exhaustive]
3215pub struct Usage {
3216 pub total_tokens: u64,
3218 pub input_tokens: u64,
3220 pub output_tokens: u64,
3222 #[serde_as(deserialize_as = "DefaultOnError")]
3224 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3225 #[serde(default)]
3226 pub thought_tokens: Option<u64>,
3227 #[serde_as(deserialize_as = "DefaultOnError")]
3229 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3230 #[serde(default)]
3231 pub cached_read_tokens: Option<u64>,
3232 #[serde_as(deserialize_as = "DefaultOnError")]
3234 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3235 #[serde(default)]
3236 pub cached_write_tokens: Option<u64>,
3237 #[serde_as(deserialize_as = "DefaultOnError")]
3243 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3244 #[serde(default)]
3245 #[serde(rename = "_meta")]
3246 pub meta: Option<Meta>,
3247}
3248
3249#[cfg(feature = "unstable_end_turn_token_usage")]
3250impl Usage {
3251 #[must_use]
3253 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3254 Self {
3255 total_tokens,
3256 input_tokens,
3257 output_tokens,
3258 thought_tokens: None,
3259 cached_read_tokens: None,
3260 cached_write_tokens: None,
3261 meta: None,
3262 }
3263 }
3264
3265 #[must_use]
3267 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3268 self.thought_tokens = thought_tokens.into_option();
3269 self
3270 }
3271
3272 #[must_use]
3274 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3275 self.cached_read_tokens = cached_read_tokens.into_option();
3276 self
3277 }
3278
3279 #[must_use]
3281 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3282 self.cached_write_tokens = cached_write_tokens.into_option();
3283 self
3284 }
3285
3286 #[must_use]
3292 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3293 self.meta = meta.into_option();
3294 self
3295 }
3296}
3297
3298#[cfg(feature = "unstable_llm_providers")]
3311#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3312#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3313#[serde(rename_all = "snake_case")]
3314#[non_exhaustive]
3315#[expect(clippy::doc_markdown)]
3316pub enum LlmProtocol {
3317 Anthropic,
3319 #[serde(rename = "openai")]
3321 OpenAi,
3322 Azure,
3324 Vertex,
3326 Bedrock,
3328 #[serde(untagged)]
3330 Other(String),
3331}
3332
3333#[cfg(feature = "unstable_llm_providers")]
3339#[serde_as]
3340#[skip_serializing_none]
3341#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3342#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3343#[serde(rename_all = "camelCase")]
3344#[non_exhaustive]
3345pub struct ProviderCurrentConfig {
3346 pub api_type: LlmProtocol,
3348 pub base_url: String,
3350 #[serde_as(deserialize_as = "DefaultOnError")]
3356 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3357 #[serde(default)]
3358 #[serde(rename = "_meta")]
3359 pub meta: Option<Meta>,
3360}
3361
3362#[cfg(feature = "unstable_llm_providers")]
3363impl ProviderCurrentConfig {
3364 #[must_use]
3366 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3367 Self {
3368 api_type,
3369 base_url: base_url.into(),
3370 meta: None,
3371 }
3372 }
3373
3374 #[must_use]
3380 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3381 self.meta = meta.into_option();
3382 self
3383 }
3384}
3385
3386#[cfg(feature = "unstable_llm_providers")]
3392#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3393#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
3394#[serde(transparent)]
3395#[from(Arc<str>, String, &'static str)]
3396#[non_exhaustive]
3397pub struct ProviderId(pub Arc<str>);
3398
3399#[cfg(feature = "unstable_llm_providers")]
3400impl ProviderId {
3401 #[must_use]
3403 pub fn new(id: impl Into<Arc<str>>) -> Self {
3404 Self(id.into())
3405 }
3406}
3407
3408#[cfg(feature = "unstable_llm_providers")]
3414#[serde_as]
3415#[skip_serializing_none]
3416#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3417#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3418#[serde(rename_all = "camelCase")]
3419#[non_exhaustive]
3420pub struct ProviderInfo {
3421 pub provider_id: ProviderId,
3423 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3425 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3426 pub supported: Vec<LlmProtocol>,
3427 pub required: bool,
3430 #[serde(default)]
3433 pub current: Option<ProviderCurrentConfig>,
3434 #[serde_as(deserialize_as = "DefaultOnError")]
3440 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3441 #[serde(default)]
3442 #[serde(rename = "_meta")]
3443 pub meta: Option<Meta>,
3444}
3445
3446#[cfg(feature = "unstable_llm_providers")]
3447impl ProviderInfo {
3448 #[must_use]
3450 pub fn new(
3451 provider_id: impl Into<ProviderId>,
3452 supported: Vec<LlmProtocol>,
3453 required: bool,
3454 current: impl IntoOption<ProviderCurrentConfig>,
3455 ) -> Self {
3456 Self {
3457 provider_id: provider_id.into(),
3458 supported,
3459 required,
3460 current: current.into_option(),
3461 meta: None,
3462 }
3463 }
3464
3465 #[must_use]
3471 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3472 self.meta = meta.into_option();
3473 self
3474 }
3475}
3476
3477#[cfg(feature = "unstable_llm_providers")]
3478crate::serde_util::default_on_null! {
3479 #[serde_as]
3485 #[skip_serializing_none]
3486 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3487 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3488 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
3489 #[serde(rename_all = "camelCase")]
3490 #[non_exhaustive]
3491 pub struct ListProvidersRequest {
3492 #[serde_as(deserialize_as = "DefaultOnError")]
3498 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3499 #[serde(default)]
3500 #[serde(rename = "_meta")]
3501 pub meta: Option<Meta>,
3502 }
3503}
3504
3505#[cfg(feature = "unstable_llm_providers")]
3506impl ListProvidersRequest {
3507 #[must_use]
3509 pub fn new() -> Self {
3510 Self::default()
3511 }
3512
3513 #[must_use]
3519 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3520 self.meta = meta.into_option();
3521 self
3522 }
3523}
3524
3525#[cfg(feature = "unstable_llm_providers")]
3531#[serde_as]
3532#[skip_serializing_none]
3533#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3534#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3535#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
3536#[serde(rename_all = "camelCase")]
3537#[non_exhaustive]
3538pub struct ListProvidersResponse {
3539 pub providers: Vec<ProviderInfo>,
3541 #[serde_as(deserialize_as = "DefaultOnError")]
3547 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3548 #[serde(default)]
3549 #[serde(rename = "_meta")]
3550 pub meta: Option<Meta>,
3551}
3552
3553#[cfg(feature = "unstable_llm_providers")]
3554impl ListProvidersResponse {
3555 #[must_use]
3557 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3558 Self {
3559 providers,
3560 meta: None,
3561 }
3562 }
3563
3564 #[must_use]
3570 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3571 self.meta = meta.into_option();
3572 self
3573 }
3574}
3575
3576#[cfg(feature = "unstable_llm_providers")]
3584#[serde_as]
3585#[skip_serializing_none]
3586#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3587#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
3588#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
3589#[serde(rename_all = "camelCase")]
3590#[non_exhaustive]
3591pub struct SetProviderRequest {
3592 pub provider_id: ProviderId,
3594 pub api_type: LlmProtocol,
3596 pub base_url: String,
3598 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3601 pub headers: HashMap<String, String>,
3602 #[serde_as(deserialize_as = "DefaultOnError")]
3608 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3609 #[serde(default)]
3610 #[serde(rename = "_meta")]
3611 pub meta: Option<Meta>,
3612}
3613
3614#[cfg(feature = "unstable_llm_providers")]
3615impl SetProviderRequest {
3616 #[must_use]
3618 pub fn new(
3619 provider_id: impl Into<ProviderId>,
3620 api_type: LlmProtocol,
3621 base_url: impl Into<String>,
3622 ) -> Self {
3623 Self {
3624 provider_id: provider_id.into(),
3625 api_type,
3626 base_url: base_url.into(),
3627 headers: HashMap::new(),
3628 meta: None,
3629 }
3630 }
3631
3632 #[must_use]
3635 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3636 self.headers = headers;
3637 self
3638 }
3639
3640 #[must_use]
3646 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3647 self.meta = meta.into_option();
3648 self
3649 }
3650}
3651
3652#[cfg(feature = "unstable_llm_providers")]
3653crate::serde_util::default_on_null! {
3654 #[serde_as]
3660 #[skip_serializing_none]
3661 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3662 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3663 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
3664 #[serde(rename_all = "camelCase")]
3665 #[non_exhaustive]
3666 pub struct SetProviderResponse {
3667 #[serde_as(deserialize_as = "DefaultOnError")]
3673 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3674 #[serde(default)]
3675 #[serde(rename = "_meta")]
3676 pub meta: Option<Meta>,
3677 }
3678}
3679
3680#[cfg(feature = "unstable_llm_providers")]
3681impl SetProviderResponse {
3682 #[must_use]
3684 pub fn new() -> Self {
3685 Self::default()
3686 }
3687
3688 #[must_use]
3694 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3695 self.meta = meta.into_option();
3696 self
3697 }
3698}
3699
3700#[cfg(feature = "unstable_llm_providers")]
3706#[serde_as]
3707#[skip_serializing_none]
3708#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3709#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3710#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
3711#[serde(rename_all = "camelCase")]
3712#[non_exhaustive]
3713pub struct DisableProviderRequest {
3714 pub provider_id: ProviderId,
3716 #[serde_as(deserialize_as = "DefaultOnError")]
3722 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3723 #[serde(default)]
3724 #[serde(rename = "_meta")]
3725 pub meta: Option<Meta>,
3726}
3727
3728#[cfg(feature = "unstable_llm_providers")]
3729impl DisableProviderRequest {
3730 #[must_use]
3732 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
3733 Self {
3734 provider_id: provider_id.into(),
3735 meta: None,
3736 }
3737 }
3738
3739 #[must_use]
3745 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3746 self.meta = meta.into_option();
3747 self
3748 }
3749}
3750
3751#[cfg(feature = "unstable_llm_providers")]
3752crate::serde_util::default_on_null! {
3753 #[serde_as]
3759 #[skip_serializing_none]
3760 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3761 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
3762 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
3763 #[serde(rename_all = "camelCase")]
3764 #[non_exhaustive]
3765 pub struct DisableProviderResponse {
3766 #[serde_as(deserialize_as = "DefaultOnError")]
3772 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3773 #[serde(default)]
3774 #[serde(rename = "_meta")]
3775 pub meta: Option<Meta>,
3776 }
3777}
3778
3779#[cfg(feature = "unstable_llm_providers")]
3780impl DisableProviderResponse {
3781 #[must_use]
3783 pub fn new() -> Self {
3784 Self::default()
3785 }
3786
3787 #[must_use]
3793 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3794 self.meta = meta.into_option();
3795 self
3796 }
3797}
3798
3799#[serde_as]
3808#[skip_serializing_none]
3809#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3810#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3811#[serde(rename_all = "camelCase")]
3812#[non_exhaustive]
3813pub struct AgentCapabilities {
3814 #[serde_as(deserialize_as = "DefaultOnError")]
3816 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3817 #[serde(default)]
3818 pub load_session: bool,
3819 #[serde_as(deserialize_as = "DefaultOnError")]
3821 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3822 #[serde(default)]
3823 pub prompt_capabilities: PromptCapabilities,
3824 #[serde_as(deserialize_as = "DefaultOnError")]
3826 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3827 #[serde(default)]
3828 pub mcp_capabilities: McpCapabilities,
3829 #[serde_as(deserialize_as = "DefaultOnError")]
3831 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3832 #[serde(default)]
3833 pub session_capabilities: SessionCapabilities,
3834 #[serde_as(deserialize_as = "DefaultOnError")]
3836 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3837 #[serde(default)]
3838 pub auth: AgentAuthCapabilities,
3839 #[cfg(feature = "unstable_llm_providers")]
3848 #[serde_as(deserialize_as = "DefaultOnError")]
3849 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3850 #[serde(default)]
3851 pub providers: Option<ProvidersCapabilities>,
3852 #[cfg(feature = "unstable_nes")]
3861 #[serde_as(deserialize_as = "DefaultOnError")]
3862 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3863 #[serde(default)]
3864 pub nes: Option<NesCapabilities>,
3865 #[cfg(feature = "unstable_nes")]
3871 #[serde_as(deserialize_as = "DefaultOnError")]
3872 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3873 #[serde(default)]
3874 pub position_encoding: Option<PositionEncodingKind>,
3875 #[serde_as(deserialize_as = "DefaultOnError")]
3881 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3882 #[serde(default)]
3883 #[serde(rename = "_meta")]
3884 pub meta: Option<Meta>,
3885}
3886
3887impl AgentCapabilities {
3888 #[must_use]
3890 pub fn new() -> Self {
3891 Self::default()
3892 }
3893
3894 #[must_use]
3896 pub fn load_session(mut self, load_session: bool) -> Self {
3897 self.load_session = load_session;
3898 self
3899 }
3900
3901 #[must_use]
3903 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
3904 self.prompt_capabilities = prompt_capabilities;
3905 self
3906 }
3907
3908 #[must_use]
3910 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
3911 self.mcp_capabilities = mcp_capabilities;
3912 self
3913 }
3914
3915 #[must_use]
3917 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
3918 self.session_capabilities = session_capabilities;
3919 self
3920 }
3921
3922 #[must_use]
3924 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
3925 self.auth = auth;
3926 self
3927 }
3928
3929 #[cfg(feature = "unstable_llm_providers")]
3935 #[must_use]
3936 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
3937 self.providers = providers.into_option();
3938 self
3939 }
3940
3941 #[cfg(feature = "unstable_nes")]
3947 #[must_use]
3948 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
3949 self.nes = nes.into_option();
3950 self
3951 }
3952
3953 #[cfg(feature = "unstable_nes")]
3957 #[must_use]
3958 pub fn position_encoding(
3959 mut self,
3960 position_encoding: impl IntoOption<PositionEncodingKind>,
3961 ) -> Self {
3962 self.position_encoding = position_encoding.into_option();
3963 self
3964 }
3965
3966 #[must_use]
3972 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3973 self.meta = meta.into_option();
3974 self
3975 }
3976}
3977
3978#[cfg(feature = "unstable_llm_providers")]
3986#[serde_as]
3987#[skip_serializing_none]
3988#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3989#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3990#[non_exhaustive]
3991pub struct ProvidersCapabilities {
3992 #[serde_as(deserialize_as = "DefaultOnError")]
3998 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3999 #[serde(default)]
4000 #[serde(rename = "_meta")]
4001 pub meta: Option<Meta>,
4002}
4003
4004#[cfg(feature = "unstable_llm_providers")]
4005impl ProvidersCapabilities {
4006 #[must_use]
4008 pub fn new() -> Self {
4009 Self::default()
4010 }
4011
4012 #[must_use]
4018 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4019 self.meta = meta.into_option();
4020 self
4021 }
4022}
4023
4024#[serde_as]
4034#[skip_serializing_none]
4035#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4036#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4037#[serde(rename_all = "camelCase")]
4038#[non_exhaustive]
4039pub struct SessionCapabilities {
4040 #[serde_as(deserialize_as = "DefaultOnError")]
4045 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4046 #[serde(default)]
4047 pub list: Option<SessionListCapabilities>,
4048 #[serde_as(deserialize_as = "DefaultOnError")]
4053 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4054 #[serde(default)]
4055 pub delete: Option<SessionDeleteCapabilities>,
4056 #[serde_as(deserialize_as = "DefaultOnError")]
4066 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4067 #[serde(default)]
4068 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4069 #[cfg(feature = "unstable_session_fork")]
4078 #[serde_as(deserialize_as = "DefaultOnError")]
4079 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4080 #[serde(default)]
4081 pub fork: Option<SessionForkCapabilities>,
4082 #[serde_as(deserialize_as = "DefaultOnError")]
4087 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4088 #[serde(default)]
4089 pub resume: Option<SessionResumeCapabilities>,
4090 #[serde_as(deserialize_as = "DefaultOnError")]
4095 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4096 #[serde(default)]
4097 pub close: Option<SessionCloseCapabilities>,
4098 #[serde_as(deserialize_as = "DefaultOnError")]
4104 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4105 #[serde(default)]
4106 #[serde(rename = "_meta")]
4107 pub meta: Option<Meta>,
4108}
4109
4110impl SessionCapabilities {
4111 #[must_use]
4113 pub fn new() -> Self {
4114 Self::default()
4115 }
4116
4117 #[must_use]
4122 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4123 self.list = list.into_option();
4124 self
4125 }
4126
4127 #[must_use]
4132 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4133 self.delete = delete.into_option();
4134 self
4135 }
4136
4137 #[must_use]
4147 pub fn additional_directories(
4148 mut self,
4149 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4150 ) -> Self {
4151 self.additional_directories = additional_directories.into_option();
4152 self
4153 }
4154
4155 #[cfg(feature = "unstable_session_fork")]
4156 #[must_use]
4161 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4162 self.fork = fork.into_option();
4163 self
4164 }
4165
4166 #[must_use]
4171 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4172 self.resume = resume.into_option();
4173 self
4174 }
4175
4176 #[must_use]
4181 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4182 self.close = close.into_option();
4183 self
4184 }
4185
4186 #[must_use]
4192 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4193 self.meta = meta.into_option();
4194 self
4195 }
4196}
4197
4198#[serde_as]
4202#[skip_serializing_none]
4203#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4204#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4205#[non_exhaustive]
4206pub struct SessionListCapabilities {
4207 #[serde_as(deserialize_as = "DefaultOnError")]
4213 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4214 #[serde(default)]
4215 #[serde(rename = "_meta")]
4216 pub meta: Option<Meta>,
4217}
4218
4219impl SessionListCapabilities {
4220 #[must_use]
4222 pub fn new() -> Self {
4223 Self::default()
4224 }
4225
4226 #[must_use]
4232 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4233 self.meta = meta.into_option();
4234 self
4235 }
4236}
4237
4238#[serde_as]
4242#[skip_serializing_none]
4243#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4244#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4245#[non_exhaustive]
4246pub struct SessionDeleteCapabilities {
4247 #[serde_as(deserialize_as = "DefaultOnError")]
4253 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4254 #[serde(default)]
4255 #[serde(rename = "_meta")]
4256 pub meta: Option<Meta>,
4257}
4258
4259impl SessionDeleteCapabilities {
4260 #[must_use]
4262 pub fn new() -> Self {
4263 Self::default()
4264 }
4265
4266 #[must_use]
4272 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4273 self.meta = meta.into_option();
4274 self
4275 }
4276}
4277
4278#[serde_as]
4285#[skip_serializing_none]
4286#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4287#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4288#[non_exhaustive]
4289pub struct SessionAdditionalDirectoriesCapabilities {
4290 #[serde_as(deserialize_as = "DefaultOnError")]
4296 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4297 #[serde(default)]
4298 #[serde(rename = "_meta")]
4299 pub meta: Option<Meta>,
4300}
4301
4302impl SessionAdditionalDirectoriesCapabilities {
4303 #[must_use]
4305 pub fn new() -> Self {
4306 Self::default()
4307 }
4308
4309 #[must_use]
4315 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4316 self.meta = meta.into_option();
4317 self
4318 }
4319}
4320
4321#[cfg(feature = "unstable_session_fork")]
4329#[serde_as]
4330#[skip_serializing_none]
4331#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4332#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4333#[non_exhaustive]
4334pub struct SessionForkCapabilities {
4335 #[serde_as(deserialize_as = "DefaultOnError")]
4341 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4342 #[serde(default)]
4343 #[serde(rename = "_meta")]
4344 pub meta: Option<Meta>,
4345}
4346
4347#[cfg(feature = "unstable_session_fork")]
4348impl SessionForkCapabilities {
4349 #[must_use]
4351 pub fn new() -> Self {
4352 Self::default()
4353 }
4354
4355 #[must_use]
4361 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4362 self.meta = meta.into_option();
4363 self
4364 }
4365}
4366
4367#[serde_as]
4371#[skip_serializing_none]
4372#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4373#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4374#[non_exhaustive]
4375pub struct SessionResumeCapabilities {
4376 #[serde_as(deserialize_as = "DefaultOnError")]
4382 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4383 #[serde(default)]
4384 #[serde(rename = "_meta")]
4385 pub meta: Option<Meta>,
4386}
4387
4388impl SessionResumeCapabilities {
4389 #[must_use]
4391 pub fn new() -> Self {
4392 Self::default()
4393 }
4394
4395 #[must_use]
4401 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4402 self.meta = meta.into_option();
4403 self
4404 }
4405}
4406
4407#[serde_as]
4411#[skip_serializing_none]
4412#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4413#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4414#[non_exhaustive]
4415pub struct SessionCloseCapabilities {
4416 #[serde_as(deserialize_as = "DefaultOnError")]
4422 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4423 #[serde(default)]
4424 #[serde(rename = "_meta")]
4425 pub meta: Option<Meta>,
4426}
4427
4428impl SessionCloseCapabilities {
4429 #[must_use]
4431 pub fn new() -> Self {
4432 Self::default()
4433 }
4434
4435 #[must_use]
4441 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4442 self.meta = meta.into_option();
4443 self
4444 }
4445}
4446
4447#[serde_as]
4460#[skip_serializing_none]
4461#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4462#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4463#[serde(rename_all = "camelCase")]
4464#[non_exhaustive]
4465pub struct PromptCapabilities {
4466 #[serde_as(deserialize_as = "DefaultOnError")]
4468 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4469 #[serde(default)]
4470 pub image: bool,
4471 #[serde_as(deserialize_as = "DefaultOnError")]
4473 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4474 #[serde(default)]
4475 pub audio: bool,
4476 #[serde_as(deserialize_as = "DefaultOnError")]
4481 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4482 #[serde(default)]
4483 pub embedded_context: bool,
4484 #[serde_as(deserialize_as = "DefaultOnError")]
4490 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4491 #[serde(default)]
4492 #[serde(rename = "_meta")]
4493 pub meta: Option<Meta>,
4494}
4495
4496impl PromptCapabilities {
4497 #[must_use]
4499 pub fn new() -> Self {
4500 Self::default()
4501 }
4502
4503 #[must_use]
4505 pub fn image(mut self, image: bool) -> Self {
4506 self.image = image;
4507 self
4508 }
4509
4510 #[must_use]
4512 pub fn audio(mut self, audio: bool) -> Self {
4513 self.audio = audio;
4514 self
4515 }
4516
4517 #[must_use]
4522 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4523 self.embedded_context = embedded_context;
4524 self
4525 }
4526
4527 #[must_use]
4533 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4534 self.meta = meta.into_option();
4535 self
4536 }
4537}
4538
4539#[serde_as]
4541#[skip_serializing_none]
4542#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4543#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4544#[serde(rename_all = "camelCase")]
4545#[non_exhaustive]
4546pub struct McpCapabilities {
4547 #[serde_as(deserialize_as = "DefaultOnError")]
4549 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4550 #[serde(default)]
4551 pub http: bool,
4552 #[serde_as(deserialize_as = "DefaultOnError")]
4554 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4555 #[serde(default)]
4556 pub sse: bool,
4557 #[cfg(feature = "unstable_mcp_over_acp")]
4563 #[serde_as(deserialize_as = "DefaultOnError")]
4564 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4565 #[serde(default)]
4566 pub acp: bool,
4567 #[serde_as(deserialize_as = "DefaultOnError")]
4573 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4574 #[serde(default)]
4575 #[serde(rename = "_meta")]
4576 pub meta: Option<Meta>,
4577}
4578
4579impl McpCapabilities {
4580 #[must_use]
4582 pub fn new() -> Self {
4583 Self::default()
4584 }
4585
4586 #[must_use]
4588 pub fn http(mut self, http: bool) -> Self {
4589 self.http = http;
4590 self
4591 }
4592
4593 #[must_use]
4595 pub fn sse(mut self, sse: bool) -> Self {
4596 self.sse = sse;
4597 self
4598 }
4599
4600 #[cfg(feature = "unstable_mcp_over_acp")]
4606 #[must_use]
4607 pub fn acp(mut self, acp: bool) -> Self {
4608 self.acp = acp;
4609 self
4610 }
4611
4612 #[must_use]
4618 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4619 self.meta = meta.into_option();
4620 self
4621 }
4622}
4623
4624#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4630#[non_exhaustive]
4631pub struct AgentMethodNames {
4632 pub initialize: &'static str,
4634 pub authenticate: &'static str,
4636 #[cfg(feature = "unstable_llm_providers")]
4638 pub providers_list: &'static str,
4639 #[cfg(feature = "unstable_llm_providers")]
4641 pub providers_set: &'static str,
4642 #[cfg(feature = "unstable_llm_providers")]
4644 pub providers_disable: &'static str,
4645 pub session_new: &'static str,
4647 pub session_load: &'static str,
4649 pub session_set_mode: &'static str,
4651 pub session_set_config_option: &'static str,
4653 pub session_prompt: &'static str,
4655 pub session_cancel: &'static str,
4657 #[cfg(feature = "unstable_mcp_over_acp")]
4659 pub mcp_message: &'static str,
4660 pub session_list: &'static str,
4662 pub session_delete: &'static str,
4664 #[cfg(feature = "unstable_session_fork")]
4666 pub session_fork: &'static str,
4667 pub session_resume: &'static str,
4669 pub session_close: &'static str,
4671 pub logout: &'static str,
4673 #[cfg(feature = "unstable_nes")]
4675 pub nes_start: &'static str,
4676 #[cfg(feature = "unstable_nes")]
4678 pub nes_suggest: &'static str,
4679 #[cfg(feature = "unstable_nes")]
4681 pub nes_accept: &'static str,
4682 #[cfg(feature = "unstable_nes")]
4684 pub nes_reject: &'static str,
4685 #[cfg(feature = "unstable_nes")]
4687 pub nes_close: &'static str,
4688 #[cfg(feature = "unstable_nes")]
4690 pub document_did_open: &'static str,
4691 #[cfg(feature = "unstable_nes")]
4693 pub document_did_change: &'static str,
4694 #[cfg(feature = "unstable_nes")]
4696 pub document_did_close: &'static str,
4697 #[cfg(feature = "unstable_nes")]
4699 pub document_did_save: &'static str,
4700 #[cfg(feature = "unstable_nes")]
4702 pub document_did_focus: &'static str,
4703}
4704
4705pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4707 initialize: INITIALIZE_METHOD_NAME,
4708 authenticate: AUTHENTICATE_METHOD_NAME,
4709 #[cfg(feature = "unstable_llm_providers")]
4710 providers_list: PROVIDERS_LIST_METHOD_NAME,
4711 #[cfg(feature = "unstable_llm_providers")]
4712 providers_set: PROVIDERS_SET_METHOD_NAME,
4713 #[cfg(feature = "unstable_llm_providers")]
4714 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4715 session_new: SESSION_NEW_METHOD_NAME,
4716 session_load: SESSION_LOAD_METHOD_NAME,
4717 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4718 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4719 session_prompt: SESSION_PROMPT_METHOD_NAME,
4720 session_cancel: SESSION_CANCEL_METHOD_NAME,
4721 #[cfg(feature = "unstable_mcp_over_acp")]
4722 mcp_message: MCP_MESSAGE_METHOD_NAME,
4723 session_list: SESSION_LIST_METHOD_NAME,
4724 session_delete: SESSION_DELETE_METHOD_NAME,
4725 #[cfg(feature = "unstable_session_fork")]
4726 session_fork: SESSION_FORK_METHOD_NAME,
4727 session_resume: SESSION_RESUME_METHOD_NAME,
4728 session_close: SESSION_CLOSE_METHOD_NAME,
4729 logout: LOGOUT_METHOD_NAME,
4730 #[cfg(feature = "unstable_nes")]
4731 nes_start: NES_START_METHOD_NAME,
4732 #[cfg(feature = "unstable_nes")]
4733 nes_suggest: NES_SUGGEST_METHOD_NAME,
4734 #[cfg(feature = "unstable_nes")]
4735 nes_accept: NES_ACCEPT_METHOD_NAME,
4736 #[cfg(feature = "unstable_nes")]
4737 nes_reject: NES_REJECT_METHOD_NAME,
4738 #[cfg(feature = "unstable_nes")]
4739 nes_close: NES_CLOSE_METHOD_NAME,
4740 #[cfg(feature = "unstable_nes")]
4741 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4742 #[cfg(feature = "unstable_nes")]
4743 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4744 #[cfg(feature = "unstable_nes")]
4745 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4746 #[cfg(feature = "unstable_nes")]
4747 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4748 #[cfg(feature = "unstable_nes")]
4749 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4750};
4751
4752pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4754pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4756#[cfg(feature = "unstable_llm_providers")]
4758pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4759#[cfg(feature = "unstable_llm_providers")]
4761pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4762#[cfg(feature = "unstable_llm_providers")]
4764pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4765pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4767pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4769pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4771pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4773pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4775pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4777pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4779pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4781#[cfg(feature = "unstable_session_fork")]
4783pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4784pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4786pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4788pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4790
4791#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4798#[derive(Clone, Debug, Serialize, Deserialize)]
4799#[serde(untagged)]
4800#[cfg_attr(feature = "schemars", schemars(inline))]
4801#[non_exhaustive]
4802#[allow(clippy::large_enum_variant)]
4803pub enum ClientRequest {
4804 InitializeRequest(InitializeRequest),
4815 AuthenticateRequest(AuthenticateRequest),
4826 #[cfg(feature = "unstable_llm_providers")]
4832 ListProvidersRequest(ListProvidersRequest),
4833 #[cfg(feature = "unstable_llm_providers")]
4839 SetProviderRequest(SetProviderRequest),
4840 #[cfg(feature = "unstable_llm_providers")]
4846 DisableProviderRequest(DisableProviderRequest),
4847 LogoutRequest(LogoutRequest),
4852 NewSessionRequest(NewSessionRequest),
4865 LoadSessionRequest(LoadSessionRequest),
4876 ListSessionsRequest(ListSessionsRequest),
4882 DeleteSessionRequest(DeleteSessionRequest),
4886 #[cfg(feature = "unstable_session_fork")]
4887 ForkSessionRequest(ForkSessionRequest),
4899 ResumeSessionRequest(ResumeSessionRequest),
4906 CloseSessionRequest(CloseSessionRequest),
4913 SetSessionModeRequest(SetSessionModeRequest),
4927 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
4929 PromptRequest(PromptRequest),
4941 #[cfg(feature = "unstable_nes")]
4942 StartNesRequest(StartNesRequest),
4948 #[cfg(feature = "unstable_nes")]
4949 SuggestNesRequest(SuggestNesRequest),
4955 #[cfg(feature = "unstable_nes")]
4956 CloseNesRequest(CloseNesRequest),
4965 #[cfg(feature = "unstable_mcp_over_acp")]
4971 MessageMcpRequest(MessageMcpRequest),
4972 ExtMethodRequest(ExtRequest),
4979}
4980
4981impl ClientRequest {
4982 #[must_use]
4984 pub fn method(&self) -> &str {
4985 match self {
4986 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
4987 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
4988 #[cfg(feature = "unstable_llm_providers")]
4989 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
4990 #[cfg(feature = "unstable_llm_providers")]
4991 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
4992 #[cfg(feature = "unstable_llm_providers")]
4993 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
4994 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
4995 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
4996 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
4997 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
4998 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
4999 #[cfg(feature = "unstable_session_fork")]
5000 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5001 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5002 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5003 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
5004 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5005 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5006 #[cfg(feature = "unstable_nes")]
5007 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5008 #[cfg(feature = "unstable_nes")]
5009 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5010 #[cfg(feature = "unstable_nes")]
5011 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5012 #[cfg(feature = "unstable_mcp_over_acp")]
5013 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5014 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5015 }
5016 }
5017}
5018
5019#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5026#[derive(Clone, Debug, Serialize, Deserialize)]
5027#[serde(untagged)]
5028#[cfg_attr(feature = "schemars", schemars(inline))]
5029#[non_exhaustive]
5030#[allow(clippy::large_enum_variant)]
5031pub enum AgentResponse {
5032 InitializeResponse(InitializeResponse),
5034 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5036 #[cfg(feature = "unstable_llm_providers")]
5038 ListProvidersResponse(ListProvidersResponse),
5039 #[cfg(feature = "unstable_llm_providers")]
5041 SetProviderResponse(#[serde(default)] SetProviderResponse),
5042 #[cfg(feature = "unstable_llm_providers")]
5044 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5045 LogoutResponse(#[serde(default)] LogoutResponse),
5047 NewSessionResponse(NewSessionResponse),
5049 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5051 ListSessionsResponse(ListSessionsResponse),
5053 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5055 #[cfg(feature = "unstable_session_fork")]
5057 ForkSessionResponse(ForkSessionResponse),
5058 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5060 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5062 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5064 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5066 PromptResponse(PromptResponse),
5068 #[cfg(feature = "unstable_nes")]
5070 StartNesResponse(StartNesResponse),
5071 #[cfg(feature = "unstable_nes")]
5073 SuggestNesResponse(SuggestNesResponse),
5074 #[cfg(feature = "unstable_nes")]
5076 CloseNesResponse(#[serde(default)] CloseNesResponse),
5077 ExtMethodResponse(ExtResponse),
5079 #[cfg(feature = "unstable_mcp_over_acp")]
5081 MessageMcpResponse(MessageMcpResponse),
5082}
5083
5084#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5091#[derive(Clone, Debug, Serialize, Deserialize)]
5092#[serde(untagged)]
5093#[cfg_attr(feature = "schemars", schemars(inline))]
5094#[non_exhaustive]
5095#[allow(clippy::large_enum_variant)]
5096pub enum ClientNotification {
5097 CancelNotification(CancelNotification),
5109 #[cfg(feature = "unstable_nes")]
5110 DidOpenDocumentNotification(DidOpenDocumentNotification),
5114 #[cfg(feature = "unstable_nes")]
5115 DidChangeDocumentNotification(DidChangeDocumentNotification),
5119 #[cfg(feature = "unstable_nes")]
5120 DidCloseDocumentNotification(DidCloseDocumentNotification),
5124 #[cfg(feature = "unstable_nes")]
5125 DidSaveDocumentNotification(DidSaveDocumentNotification),
5129 #[cfg(feature = "unstable_nes")]
5130 DidFocusDocumentNotification(DidFocusDocumentNotification),
5134 #[cfg(feature = "unstable_nes")]
5135 AcceptNesNotification(AcceptNesNotification),
5139 #[cfg(feature = "unstable_nes")]
5140 RejectNesNotification(RejectNesNotification),
5144 #[cfg(feature = "unstable_mcp_over_acp")]
5150 MessageMcpNotification(MessageMcpNotification),
5151 ExtNotification(ExtNotification),
5158}
5159
5160impl ClientNotification {
5161 #[must_use]
5163 pub fn method(&self) -> &str {
5164 match self {
5165 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5166 #[cfg(feature = "unstable_nes")]
5167 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5168 #[cfg(feature = "unstable_nes")]
5169 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5170 #[cfg(feature = "unstable_nes")]
5171 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5172 #[cfg(feature = "unstable_nes")]
5173 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5174 #[cfg(feature = "unstable_nes")]
5175 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5176 #[cfg(feature = "unstable_nes")]
5177 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5178 #[cfg(feature = "unstable_nes")]
5179 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5180 #[cfg(feature = "unstable_mcp_over_acp")]
5181 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5182 Self::ExtNotification(ext_notification) => &ext_notification.method,
5183 }
5184 }
5185}
5186
5187#[serde_as]
5191#[skip_serializing_none]
5192#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5193#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5194#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME)))]
5195#[serde(rename_all = "camelCase")]
5196#[non_exhaustive]
5197pub struct CancelNotification {
5198 pub session_id: SessionId,
5200 #[serde_as(deserialize_as = "DefaultOnError")]
5206 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5207 #[serde(default)]
5208 #[serde(rename = "_meta")]
5209 pub meta: Option<Meta>,
5210}
5211
5212impl CancelNotification {
5213 #[must_use]
5215 pub fn new(session_id: impl Into<SessionId>) -> Self {
5216 Self {
5217 session_id: session_id.into(),
5218 meta: None,
5219 }
5220 }
5221
5222 #[must_use]
5228 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5229 self.meta = meta.into_option();
5230 self
5231 }
5232}
5233
5234#[cfg(test)]
5235mod test_serialization {
5236 use super::*;
5237 use serde_json::json;
5238
5239 fn test_meta() -> Meta {
5240 json!({ "source": "test" }).as_object().unwrap().clone()
5241 }
5242
5243 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5244 serde_json::to_string(value)
5245 .unwrap()
5246 .matches("\"_meta\"")
5247 .count()
5248 }
5249
5250 #[test]
5251 fn test_initialize_capabilities_default_on_malformed_values() {
5252 let request: InitializeRequest = serde_json::from_value(json!({
5253 "protocolVersion": 1,
5254 "clientCapabilities": false
5255 }))
5256 .unwrap();
5257 assert_eq!(request.client_capabilities, ClientCapabilities::default());
5258
5259 let response: InitializeResponse = serde_json::from_value(json!({
5260 "protocolVersion": 1,
5261 "agentCapabilities": false
5262 }))
5263 .unwrap();
5264 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
5265 }
5266
5267 #[test]
5268 fn test_agent_capabilities_default_on_malformed_values() {
5269 let capabilities: AgentCapabilities = serde_json::from_value(json!({
5270 "loadSession": "yes",
5271 "promptCapabilities": {
5272 "image": "yes",
5273 "audio": true,
5274 "embeddedContext": {}
5275 },
5276 "mcpCapabilities": {
5277 "http": "yes",
5278 "sse": true
5279 },
5280 "sessionCapabilities": false,
5281 "auth": false
5282 }))
5283 .unwrap();
5284
5285 assert!(!capabilities.load_session);
5286 assert!(!capabilities.prompt_capabilities.image);
5287 assert!(capabilities.prompt_capabilities.audio);
5288 assert!(!capabilities.prompt_capabilities.embedded_context);
5289 assert!(!capabilities.mcp_capabilities.http);
5290 assert!(capabilities.mcp_capabilities.sse);
5291 assert_eq!(
5292 capabilities.session_capabilities,
5293 SessionCapabilities::default()
5294 );
5295 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
5296 }
5297
5298 #[test]
5299 fn test_mcp_server_stdio_serialization() {
5300 let server = McpServer::Stdio(
5301 McpServerStdio::new("test-server", "/usr/bin/server")
5302 .args(vec!["--port".to_string(), "3000".to_string()])
5303 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5304 );
5305
5306 let json = serde_json::to_value(&server).unwrap();
5307 assert_eq!(
5308 json,
5309 json!({
5310 "name": "test-server",
5311 "command": "/usr/bin/server",
5312 "args": ["--port", "3000"],
5313 "env": [
5314 {
5315 "name": "API_KEY",
5316 "value": "secret123"
5317 }
5318 ]
5319 })
5320 );
5321
5322 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5323 match deserialized {
5324 McpServer::Stdio(McpServerStdio {
5325 name,
5326 command,
5327 args,
5328 env,
5329 meta: _,
5330 }) => {
5331 assert_eq!(name, "test-server");
5332 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5333 assert_eq!(args, vec!["--port", "3000"]);
5334 assert_eq!(env.len(), 1);
5335 assert_eq!(env[0].name, "API_KEY");
5336 assert_eq!(env[0].value, "secret123");
5337 }
5338 _ => panic!("Expected Stdio variant"),
5339 }
5340 }
5341
5342 #[test]
5343 fn test_mcp_server_http_serialization() {
5344 let server = McpServer::Http(
5345 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5346 HttpHeader::new("Authorization", "Bearer token123"),
5347 HttpHeader::new("Content-Type", "application/json"),
5348 ]),
5349 );
5350
5351 let json = serde_json::to_value(&server).unwrap();
5352 assert_eq!(
5353 json,
5354 json!({
5355 "type": "http",
5356 "name": "http-server",
5357 "url": "https://api.example.com",
5358 "headers": [
5359 {
5360 "name": "Authorization",
5361 "value": "Bearer token123"
5362 },
5363 {
5364 "name": "Content-Type",
5365 "value": "application/json"
5366 }
5367 ]
5368 })
5369 );
5370
5371 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5372 match deserialized {
5373 McpServer::Http(McpServerHttp {
5374 name,
5375 url,
5376 headers,
5377 meta: _,
5378 }) => {
5379 assert_eq!(name, "http-server");
5380 assert_eq!(url, "https://api.example.com");
5381 assert_eq!(headers.len(), 2);
5382 assert_eq!(headers[0].name, "Authorization");
5383 assert_eq!(headers[0].value, "Bearer token123");
5384 assert_eq!(headers[1].name, "Content-Type");
5385 assert_eq!(headers[1].value, "application/json");
5386 }
5387 _ => panic!("Expected Http variant"),
5388 }
5389 }
5390
5391 #[cfg(feature = "unstable_mcp_over_acp")]
5392 #[test]
5393 fn test_mcp_server_acp_serialization() {
5394 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5395
5396 let json = serde_json::to_value(&server).unwrap();
5397 assert_eq!(
5398 json,
5399 json!({
5400 "type": "acp",
5401 "name": "project-tools",
5402 "serverId": "project-tools-id"
5403 })
5404 );
5405
5406 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5407 match deserialized {
5408 McpServer::Acp(McpServerAcp {
5409 name,
5410 server_id: id,
5411 meta: _,
5412 }) => {
5413 assert_eq!(name, "project-tools");
5414 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5415 }
5416 _ => panic!("Expected Acp variant"),
5417 }
5418 }
5419
5420 #[cfg(feature = "unstable_mcp_over_acp")]
5421 #[test]
5422 fn test_client_mcp_message_method_names() {
5423 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5424
5425 assert_eq!(
5426 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5427 .method(),
5428 "mcp/message"
5429 );
5430 assert_eq!(
5431 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5432 "conn-1",
5433 "notifications/progress"
5434 ))
5435 .method(),
5436 "mcp/message"
5437 );
5438 }
5439
5440 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5441 #[test]
5442 fn test_mcp_server_acp_schema() {
5443 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5444 assert!(json_contains_entry(
5445 &mcp_server_schema,
5446 "const",
5447 &json!("acp")
5448 ));
5449 assert!(json_contains_entry(
5450 &mcp_server_schema,
5451 "$ref",
5452 &json!("#/$defs/McpServerAcp")
5453 ));
5454
5455 let capabilities_schema =
5456 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5457 assert!(json_contains_key(&capabilities_schema, "acp"));
5458 }
5459
5460 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5461 fn json_contains_entry(
5462 value: &serde_json::Value,
5463 key: &str,
5464 expected: &serde_json::Value,
5465 ) -> bool {
5466 match value {
5467 serde_json::Value::Object(map) => {
5468 map.get(key) == Some(expected)
5469 || map
5470 .values()
5471 .any(|value| json_contains_entry(value, key, expected))
5472 }
5473 serde_json::Value::Array(values) => values
5474 .iter()
5475 .any(|value| json_contains_entry(value, key, expected)),
5476 _ => false,
5477 }
5478 }
5479
5480 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5481 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5482 match value {
5483 serde_json::Value::Object(map) => {
5484 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5485 }
5486 serde_json::Value::Array(values) => {
5487 values.iter().any(|value| json_contains_key(value, key))
5488 }
5489 _ => false,
5490 }
5491 }
5492
5493 #[test]
5494 fn test_mcp_server_sse_serialization() {
5495 let server = McpServer::Sse(
5496 McpServerSse::new("sse-server", "https://sse.example.com/events")
5497 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5498 );
5499
5500 let json = serde_json::to_value(&server).unwrap();
5501 assert_eq!(
5502 json,
5503 json!({
5504 "type": "sse",
5505 "name": "sse-server",
5506 "url": "https://sse.example.com/events",
5507 "headers": [
5508 {
5509 "name": "X-API-Key",
5510 "value": "apikey456"
5511 }
5512 ]
5513 })
5514 );
5515
5516 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5517 match deserialized {
5518 McpServer::Sse(McpServerSse {
5519 name,
5520 url,
5521 headers,
5522 meta: _,
5523 }) => {
5524 assert_eq!(name, "sse-server");
5525 assert_eq!(url, "https://sse.example.com/events");
5526 assert_eq!(headers.len(), 1);
5527 assert_eq!(headers[0].name, "X-API-Key");
5528 assert_eq!(headers[0].value, "apikey456");
5529 }
5530 _ => panic!("Expected Sse variant"),
5531 }
5532 }
5533
5534 #[test]
5535 fn test_session_config_option_category_known_variants() {
5536 assert_eq!(
5538 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5539 json!("mode")
5540 );
5541 assert_eq!(
5542 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5543 json!("model")
5544 );
5545 assert_eq!(
5546 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5547 json!("model_config")
5548 );
5549 assert_eq!(
5550 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5551 json!("thought_level")
5552 );
5553
5554 assert_eq!(
5556 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5557 SessionConfigOptionCategory::Mode
5558 );
5559 assert_eq!(
5560 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5561 SessionConfigOptionCategory::Model
5562 );
5563 assert_eq!(
5564 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5565 SessionConfigOptionCategory::ModelConfig
5566 );
5567 assert_eq!(
5568 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5569 SessionConfigOptionCategory::ThoughtLevel
5570 );
5571 }
5572
5573 #[test]
5574 fn test_session_config_option_category_unknown_variants() {
5575 let unknown: SessionConfigOptionCategory =
5577 serde_json::from_str("\"some_future_category\"").unwrap();
5578 assert_eq!(
5579 unknown,
5580 SessionConfigOptionCategory::Other("some_future_category".to_string())
5581 );
5582
5583 let json = serde_json::to_value(&unknown).unwrap();
5585 assert_eq!(json, json!("some_future_category"));
5586 }
5587
5588 #[test]
5589 fn test_session_config_option_category_custom_categories() {
5590 let custom: SessionConfigOptionCategory =
5592 serde_json::from_str("\"_my_custom_category\"").unwrap();
5593 assert_eq!(
5594 custom,
5595 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5596 );
5597
5598 let json = serde_json::to_value(&custom).unwrap();
5600 assert_eq!(json, json!("_my_custom_category"));
5601
5602 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5604 assert_eq!(
5605 deserialized,
5606 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5607 );
5608 }
5609
5610 #[test]
5611 fn test_auth_method_agent_serialization() {
5612 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5613
5614 let json = serde_json::to_value(&method).unwrap();
5615 assert_eq!(
5616 json,
5617 json!({
5618 "id": "default-auth",
5619 "name": "Default Auth"
5620 })
5621 );
5622 assert!(!json.as_object().unwrap().contains_key("description"));
5624 assert!(!json.as_object().unwrap().contains_key("type"));
5626
5627 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5628 match deserialized {
5629 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5630 assert_eq!(id.0.as_ref(), "default-auth");
5631 assert_eq!(name, "Default Auth");
5632 }
5633 _ => panic!("Expected Agent variant"),
5634 }
5635 }
5636
5637 #[test]
5638 fn test_auth_method_explicit_agent_deserialization() {
5639 let json = json!({
5641 "id": "agent-auth",
5642 "name": "Agent Auth",
5643 "type": "agent"
5644 });
5645
5646 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5647 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5648 }
5649
5650 #[test]
5651 fn test_session_delete_serialization() {
5652 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5653 assert_eq!(
5654 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5655 "session/delete"
5656 );
5657 assert_eq!(
5658 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5659 json!({
5660 "sessionId": "sess_abc123"
5661 })
5662 );
5663 assert_eq!(
5664 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5665 json!({})
5666 );
5667 assert_eq!(
5668 serde_json::to_value(
5669 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5670 )
5671 .unwrap(),
5672 json!({
5673 "delete": {}
5674 })
5675 );
5676 }
5677 #[test]
5678 fn test_session_additional_directories_serialization() {
5679 assert_eq!(
5680 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5681 json!({
5682 "cwd": "/home/user/project",
5683 "mcpServers": []
5684 })
5685 );
5686 assert_eq!(
5687 serde_json::to_value(
5688 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5689 PathBuf::from("/home/user/shared-lib"),
5690 PathBuf::from("/home/user/product-docs"),
5691 ])
5692 )
5693 .unwrap(),
5694 json!({
5695 "cwd": "/home/user/project",
5696 "additionalDirectories": [
5697 "/home/user/shared-lib",
5698 "/home/user/product-docs"
5699 ],
5700 "mcpServers": []
5701 })
5702 );
5703 assert_eq!(
5704 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5705 json!({
5706 "sessionId": "sess_abc123",
5707 "cwd": "/home/user/project"
5708 })
5709 );
5710 assert_eq!(
5711 serde_json::to_value(
5712 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5713 PathBuf::from("/home/user/shared-lib"),
5714 PathBuf::from("/home/user/product-docs"),
5715 ])
5716 )
5717 .unwrap(),
5718 json!({
5719 "sessionId": "sess_abc123",
5720 "cwd": "/home/user/project",
5721 "additionalDirectories": [
5722 "/home/user/shared-lib",
5723 "/home/user/product-docs"
5724 ]
5725 })
5726 );
5727 assert_eq!(
5728 serde_json::from_value::<SessionInfo>(json!({
5729 "sessionId": "sess_abc123",
5730 "cwd": "/home/user/project"
5731 }))
5732 .unwrap()
5733 .additional_directories,
5734 Vec::<PathBuf>::new()
5735 );
5736 }
5737 #[test]
5738 fn test_session_additional_directories_capabilities_serialization() {
5739 assert_eq!(
5740 serde_json::to_value(
5741 SessionCapabilities::new()
5742 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5743 )
5744 .unwrap(),
5745 json!({
5746 "additionalDirectories": {}
5747 })
5748 );
5749 }
5750
5751 #[test]
5752 fn test_auth_method_terminal_serialization() {
5753 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5754
5755 let json = serde_json::to_value(&method).unwrap();
5756 assert_eq!(
5757 json,
5758 json!({
5759 "id": "tui-auth",
5760 "name": "Terminal Auth",
5761 "type": "terminal"
5762 })
5763 );
5764 assert!(!json.as_object().unwrap().contains_key("args"));
5766 assert!(!json.as_object().unwrap().contains_key("env"));
5767
5768 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5769 match deserialized {
5770 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5771 assert!(args.is_empty());
5772 assert!(env.is_empty());
5773 }
5774 _ => panic!("Expected Terminal variant"),
5775 }
5776 }
5777
5778 #[test]
5779 fn test_auth_method_terminal_with_args_and_env_serialization() {
5780 use std::collections::HashMap;
5781
5782 let mut env = HashMap::new();
5783 env.insert("TERM".to_string(), "xterm-256color".to_string());
5784
5785 let method = AuthMethod::Terminal(
5786 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5787 .args(vec!["--interactive".to_string(), "--color".to_string()])
5788 .env(env),
5789 );
5790
5791 let json = serde_json::to_value(&method).unwrap();
5792 assert_eq!(
5793 json,
5794 json!({
5795 "id": "tui-auth",
5796 "name": "Terminal Auth",
5797 "type": "terminal",
5798 "args": ["--interactive", "--color"],
5799 "env": {
5800 "TERM": "xterm-256color"
5801 }
5802 })
5803 );
5804
5805 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5806 match deserialized {
5807 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5808 assert_eq!(args, vec!["--interactive", "--color"]);
5809 assert_eq!(env.len(), 1);
5810 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
5811 }
5812 _ => panic!("Expected Terminal variant"),
5813 }
5814 }
5815
5816 #[test]
5817 fn test_session_config_option_value_id_serialize() {
5818 let val = SessionConfigOptionValue::value_id("model-1");
5819 let json = serde_json::to_value(&val).unwrap();
5820 assert_eq!(json, json!({ "value": "model-1" }));
5822 assert!(!json.as_object().unwrap().contains_key("type"));
5823 }
5824
5825 #[test]
5826 fn test_session_config_option_value_boolean_serialize() {
5827 let val = SessionConfigOptionValue::boolean(true);
5828 let json = serde_json::to_value(&val).unwrap();
5829 assert_eq!(json, json!({ "type": "boolean", "value": true }));
5830 }
5831
5832 #[test]
5833 fn test_session_config_option_value_deserialize_no_type() {
5834 let json = json!({ "value": "model-1" });
5836 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5837 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
5838 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
5839 }
5840
5841 #[test]
5842 fn test_session_config_option_value_deserialize_boolean() {
5843 let json = json!({ "type": "boolean", "value": true });
5844 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5845 assert_eq!(val, SessionConfigOptionValue::boolean(true));
5846 assert_eq!(val.as_bool(), Some(true));
5847 }
5848
5849 #[test]
5850 fn test_session_config_option_value_deserialize_boolean_false() {
5851 let json = json!({ "type": "boolean", "value": false });
5852 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5853 assert_eq!(val, SessionConfigOptionValue::boolean(false));
5854 assert_eq!(val.as_bool(), Some(false));
5855 }
5856
5857 #[test]
5858 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
5859 let json = json!({ "type": "text", "value": "freeform input" });
5861 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5862 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
5863 }
5864
5865 #[test]
5866 fn test_session_config_option_value_roundtrip_value_id() {
5867 let original = SessionConfigOptionValue::value_id("option-a");
5868 let json = serde_json::to_value(&original).unwrap();
5869 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5870 assert_eq!(original, roundtripped);
5871 }
5872
5873 #[test]
5874 fn test_session_config_option_value_roundtrip_boolean() {
5875 let original = SessionConfigOptionValue::boolean(false);
5876 let json = serde_json::to_value(&original).unwrap();
5877 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5878 assert_eq!(original, roundtripped);
5879 }
5880
5881 #[test]
5882 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
5883 let json = json!({ "type": "boolean", "value": "not a bool" });
5885 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
5886 assert!(result.is_ok());
5888 assert_eq!(
5889 result.unwrap().as_value_id().unwrap().to_string(),
5890 "not a bool"
5891 );
5892 }
5893
5894 #[test]
5895 fn test_session_config_option_value_from_impls() {
5896 let from_str: SessionConfigOptionValue = "model-1".into();
5897 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
5898
5899 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
5900 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
5901
5902 let from_bool: SessionConfigOptionValue = true.into();
5903 assert_eq!(from_bool.as_bool(), Some(true));
5904 }
5905
5906 #[test]
5907 fn test_set_session_config_option_request_value_id() {
5908 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
5909 let json = serde_json::to_value(&req).unwrap();
5910 assert_eq!(
5911 json,
5912 json!({
5913 "sessionId": "sess_1",
5914 "configId": "model",
5915 "value": "model-1"
5916 })
5917 );
5918 assert!(!json.as_object().unwrap().contains_key("type"));
5920 }
5921
5922 #[test]
5923 fn test_set_session_config_option_request_boolean() {
5924 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
5925 let json = serde_json::to_value(&req).unwrap();
5926 assert_eq!(
5927 json,
5928 json!({
5929 "sessionId": "sess_1",
5930 "configId": "brave_mode",
5931 "type": "boolean",
5932 "value": true
5933 })
5934 );
5935 }
5936
5937 #[test]
5938 fn test_set_session_config_option_request_deserialize_no_type() {
5939 let json = json!({
5941 "sessionId": "sess_1",
5942 "configId": "model",
5943 "value": "model-1"
5944 });
5945 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5946 assert_eq!(req.session_id.to_string(), "sess_1");
5947 assert_eq!(req.config_id.to_string(), "model");
5948 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
5949 }
5950
5951 #[test]
5952 fn test_set_session_config_option_request_deserialize_boolean() {
5953 let json = json!({
5954 "sessionId": "sess_1",
5955 "configId": "brave_mode",
5956 "type": "boolean",
5957 "value": true
5958 });
5959 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5960 assert_eq!(req.value.as_bool(), Some(true));
5961 }
5962
5963 #[test]
5964 fn test_set_session_config_option_request_roundtrip_value_id() {
5965 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
5966 let json = serde_json::to_value(&original).unwrap();
5967 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5968 assert_eq!(original, roundtripped);
5969 }
5970
5971 #[test]
5972 fn test_set_session_config_option_request_roundtrip_boolean() {
5973 let original = SetSessionConfigOptionRequest::new("s", "c", false);
5974 let json = serde_json::to_value(&original).unwrap();
5975 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5976 assert_eq!(original, roundtripped);
5977 }
5978
5979 #[test]
5980 fn test_session_config_boolean_serialization() {
5981 let cfg = SessionConfigBoolean::new(true);
5982 let json = serde_json::to_value(&cfg).unwrap();
5983 assert_eq!(json, json!({ "currentValue": true }));
5984
5985 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
5986 assert!(deserialized.current_value);
5987 }
5988
5989 #[test]
5990 fn test_session_config_option_boolean_variant() {
5991 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
5992 .description("Skip confirmation prompts")
5993 .meta(test_meta());
5994 assert_eq!(serialized_meta_key_count(&opt), 1);
5995
5996 let json = serde_json::to_value(&opt).unwrap();
5997 assert_eq!(
5998 json,
5999 json!({
6000 "id": "brave_mode",
6001 "name": "Brave Mode",
6002 "description": "Skip confirmation prompts",
6003 "type": "boolean",
6004 "currentValue": false,
6005 "_meta": {
6006 "source": "test"
6007 }
6008 })
6009 );
6010
6011 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6012 assert_eq!(deserialized.id.to_string(), "brave_mode");
6013 assert_eq!(deserialized.name, "Brave Mode");
6014 match deserialized.kind {
6015 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6016 _ => panic!("Expected Boolean kind"),
6017 }
6018 }
6019
6020 #[test]
6021 fn test_session_config_option_select_still_works() {
6022 let opt = SessionConfigOption::select(
6024 "model",
6025 "Model",
6026 "model-1",
6027 vec![
6028 SessionConfigSelectOption::new("model-1", "Model 1"),
6029 SessionConfigSelectOption::new("model-2", "Model 2"),
6030 ],
6031 )
6032 .meta(test_meta());
6033 assert_eq!(serialized_meta_key_count(&opt), 1);
6034
6035 let json = serde_json::to_value(&opt).unwrap();
6036 assert_eq!(json["type"], "select");
6037 assert_eq!(json["currentValue"], "model-1");
6038 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6039 assert_eq!(json["_meta"]["source"], "test");
6040
6041 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6042 match deserialized.kind {
6043 SessionConfigKind::Select(ref s) => {
6044 assert_eq!(s.current_value.to_string(), "model-1");
6045 }
6046 _ => panic!("Expected Select kind"),
6047 }
6048 }
6049
6050 #[cfg(feature = "unstable_llm_providers")]
6051 #[test]
6052 fn test_llm_protocol_known_variants() {
6053 assert_eq!(
6054 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6055 json!("anthropic")
6056 );
6057 assert_eq!(
6058 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6059 json!("openai")
6060 );
6061 assert_eq!(
6062 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6063 json!("azure")
6064 );
6065 assert_eq!(
6066 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6067 json!("vertex")
6068 );
6069 assert_eq!(
6070 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6071 json!("bedrock")
6072 );
6073
6074 assert_eq!(
6075 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6076 LlmProtocol::Anthropic
6077 );
6078 assert_eq!(
6079 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6080 LlmProtocol::OpenAi
6081 );
6082 assert_eq!(
6083 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6084 LlmProtocol::Azure
6085 );
6086 assert_eq!(
6087 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6088 LlmProtocol::Vertex
6089 );
6090 assert_eq!(
6091 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6092 LlmProtocol::Bedrock
6093 );
6094 }
6095
6096 #[cfg(feature = "unstable_llm_providers")]
6097 #[test]
6098 fn test_llm_protocol_unknown_variant() {
6099 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6100 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6101
6102 let json = serde_json::to_value(&unknown).unwrap();
6103 assert_eq!(json, json!("cohere"));
6104 }
6105
6106 #[cfg(feature = "unstable_llm_providers")]
6107 #[test]
6108 fn test_provider_current_config_serialization() {
6109 let config =
6110 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6111
6112 let json = serde_json::to_value(&config).unwrap();
6113 assert_eq!(
6114 json,
6115 json!({
6116 "apiType": "anthropic",
6117 "baseUrl": "https://api.anthropic.com"
6118 })
6119 );
6120
6121 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6122 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6123 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6124 }
6125
6126 #[cfg(feature = "unstable_llm_providers")]
6127 #[test]
6128 fn test_provider_info_with_current_config() {
6129 let info = ProviderInfo::new(
6130 "main",
6131 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6132 true,
6133 Some(ProviderCurrentConfig::new(
6134 LlmProtocol::Anthropic,
6135 "https://api.anthropic.com",
6136 )),
6137 );
6138
6139 let json = serde_json::to_value(&info).unwrap();
6140 assert_eq!(
6141 json,
6142 json!({
6143 "providerId": "main",
6144 "supported": ["anthropic", "openai"],
6145 "required": true,
6146 "current": {
6147 "apiType": "anthropic",
6148 "baseUrl": "https://api.anthropic.com"
6149 }
6150 })
6151 );
6152
6153 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6154 assert_eq!(deserialized.provider_id.to_string(), "main");
6155 assert_eq!(deserialized.supported.len(), 2);
6156 assert!(deserialized.required);
6157 assert!(deserialized.current.is_some());
6158 assert_eq!(
6159 deserialized.current.as_ref().unwrap().api_type,
6160 LlmProtocol::Anthropic
6161 );
6162 }
6163
6164 #[cfg(feature = "unstable_llm_providers")]
6165 #[test]
6166 fn test_provider_info_disabled() {
6167 let info = ProviderInfo::new(
6168 "secondary",
6169 vec![LlmProtocol::OpenAi],
6170 false,
6171 None::<ProviderCurrentConfig>,
6172 );
6173
6174 let json = serde_json::to_value(&info).unwrap();
6175 assert_eq!(
6176 json,
6177 json!({
6178 "providerId": "secondary",
6179 "supported": ["openai"],
6180 "required": false
6181 })
6182 );
6183
6184 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6185 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6186 assert!(!deserialized.required);
6187 assert!(deserialized.current.is_none());
6188 }
6189
6190 #[cfg(feature = "unstable_llm_providers")]
6191 #[test]
6192 fn test_provider_info_missing_current_defaults_to_none() {
6193 let json = json!({
6195 "providerId": "main",
6196 "supported": ["anthropic"],
6197 "required": true
6198 });
6199 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6200 assert!(deserialized.current.is_none());
6201 }
6202
6203 #[cfg(feature = "unstable_llm_providers")]
6204 #[test]
6205 fn test_provider_info_explicit_null_current_decodes_to_none() {
6206 let json = json!({
6210 "providerId": "main",
6211 "supported": ["anthropic"],
6212 "required": true,
6213 "current": null
6214 });
6215 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6216 assert!(deserialized.current.is_none());
6217 }
6218
6219 #[cfg(feature = "unstable_llm_providers")]
6220 #[test]
6221 fn test_list_providers_response_serialization() {
6222 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6223 "main",
6224 vec![LlmProtocol::Anthropic],
6225 true,
6226 Some(ProviderCurrentConfig::new(
6227 LlmProtocol::Anthropic,
6228 "https://api.anthropic.com",
6229 )),
6230 )]);
6231
6232 let json = serde_json::to_value(&response).unwrap();
6233 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6234 assert_eq!(json["providers"][0]["providerId"], "main");
6235
6236 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6237 assert_eq!(deserialized.providers.len(), 1);
6238 }
6239
6240 #[cfg(feature = "unstable_llm_providers")]
6241 #[test]
6242 fn test_set_provider_request_serialization() {
6243 use std::collections::HashMap;
6244
6245 let mut headers = HashMap::new();
6246 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6247
6248 let request =
6249 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6250 .headers(headers);
6251
6252 let json = serde_json::to_value(&request).unwrap();
6253 assert_eq!(
6254 json,
6255 json!({
6256 "providerId": "main",
6257 "apiType": "openai",
6258 "baseUrl": "https://api.openai.com/v1",
6259 "headers": {
6260 "Authorization": "Bearer sk-test"
6261 }
6262 })
6263 );
6264
6265 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6266 assert_eq!(deserialized.provider_id.to_string(), "main");
6267 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6268 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6269 assert_eq!(deserialized.headers.len(), 1);
6270 assert_eq!(
6271 deserialized.headers.get("Authorization").unwrap(),
6272 "Bearer sk-test"
6273 );
6274 }
6275
6276 #[cfg(feature = "unstable_llm_providers")]
6277 #[test]
6278 fn test_set_provider_request_omits_empty_headers() {
6279 let request =
6280 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6281
6282 let json = serde_json::to_value(&request).unwrap();
6283 assert!(!json.as_object().unwrap().contains_key("headers"));
6285 }
6286
6287 #[cfg(feature = "unstable_llm_providers")]
6288 #[test]
6289 fn test_disable_provider_request_serialization() {
6290 let request = DisableProviderRequest::new("secondary");
6291
6292 let json = serde_json::to_value(&request).unwrap();
6293 assert_eq!(json, json!({ "providerId": "secondary" }));
6294
6295 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6296 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6297 }
6298
6299 #[cfg(feature = "unstable_llm_providers")]
6300 #[test]
6301 fn test_providers_capabilities_serialization() {
6302 let caps = ProvidersCapabilities::new();
6303
6304 let json = serde_json::to_value(&caps).unwrap();
6305 assert_eq!(json, json!({}));
6306
6307 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6308 assert!(deserialized.meta.is_none());
6309 }
6310
6311 #[cfg(feature = "unstable_llm_providers")]
6312 #[test]
6313 fn test_agent_capabilities_with_providers() {
6314 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6315
6316 let json = serde_json::to_value(&caps).unwrap();
6317 assert_eq!(json["providers"], json!({}));
6318
6319 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6320 assert!(deserialized.providers.is_some());
6321 }
6322
6323 #[test]
6324 fn prompt_request_rejects_malformed_content_block() {
6325 use serde_json::json;
6326
6327 assert!(
6328 serde_json::from_value::<PromptRequest>(json!({
6329 "sessionId": "sess-1",
6330 "prompt": [{"type": "text"}]
6331 }))
6332 .is_err()
6333 );
6334 }
6335
6336 #[test]
6337 fn prompt_request_rejects_non_array_prompt() {
6338 use serde_json::json;
6339
6340 assert!(
6341 serde_json::from_value::<PromptRequest>(json!({
6342 "sessionId": "sess-1",
6343 "prompt": "hello"
6344 }))
6345 .is_err()
6346 );
6347 }
6348}