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
333#[serde_as]
335#[skip_serializing_none]
336#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
337#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
338#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME)))]
339#[serde(rename_all = "camelCase")]
340#[non_exhaustive]
341pub struct AuthenticateResponse {
342 #[serde_as(deserialize_as = "DefaultOnError")]
348 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
349 #[serde(default)]
350 #[serde(rename = "_meta")]
351 pub meta: Option<Meta>,
352}
353
354impl AuthenticateResponse {
355 #[must_use]
357 pub fn new() -> Self {
358 Self::default()
359 }
360
361 #[must_use]
367 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
368 self.meta = meta.into_option();
369 self
370 }
371}
372
373#[serde_as]
379#[skip_serializing_none]
380#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
381#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
382#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
383#[serde(rename_all = "camelCase")]
384#[non_exhaustive]
385pub struct LogoutRequest {
386 #[serde_as(deserialize_as = "DefaultOnError")]
392 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
393 #[serde(default)]
394 #[serde(rename = "_meta")]
395 pub meta: Option<Meta>,
396}
397
398impl LogoutRequest {
399 #[must_use]
401 pub fn new() -> Self {
402 Self::default()
403 }
404
405 #[must_use]
411 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
412 self.meta = meta.into_option();
413 self
414 }
415}
416
417#[serde_as]
419#[skip_serializing_none]
420#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
421#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
422#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME)))]
423#[serde(rename_all = "camelCase")]
424#[non_exhaustive]
425pub struct LogoutResponse {
426 #[serde_as(deserialize_as = "DefaultOnError")]
432 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
433 #[serde(default)]
434 #[serde(rename = "_meta")]
435 pub meta: Option<Meta>,
436}
437
438impl LogoutResponse {
439 #[must_use]
441 pub fn new() -> Self {
442 Self::default()
443 }
444
445 #[must_use]
451 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
452 self.meta = meta.into_option();
453 self
454 }
455}
456
457#[serde_as]
459#[skip_serializing_none]
460#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
461#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
462#[serde(rename_all = "camelCase")]
463#[non_exhaustive]
464pub struct AgentAuthCapabilities {
465 #[serde_as(deserialize_as = "DefaultOnError")]
470 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
471 #[serde(default)]
472 pub logout: Option<LogoutCapabilities>,
473 #[serde_as(deserialize_as = "DefaultOnError")]
479 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
480 #[serde(default)]
481 #[serde(rename = "_meta")]
482 pub meta: Option<Meta>,
483}
484
485impl AgentAuthCapabilities {
486 #[must_use]
488 pub fn new() -> Self {
489 Self::default()
490 }
491
492 #[must_use]
494 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
495 self.logout = logout.into_option();
496 self
497 }
498
499 #[must_use]
505 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
506 self.meta = meta.into_option();
507 self
508 }
509}
510
511#[serde_as]
515#[skip_serializing_none]
516#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
517#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
518#[non_exhaustive]
519pub struct LogoutCapabilities {
520 #[serde_as(deserialize_as = "DefaultOnError")]
526 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
527 #[serde(default)]
528 #[serde(rename = "_meta")]
529 pub meta: Option<Meta>,
530}
531
532impl LogoutCapabilities {
533 #[must_use]
535 pub fn new() -> Self {
536 Self::default()
537 }
538
539 #[must_use]
545 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
546 self.meta = meta.into_option();
547 self
548 }
549}
550
551#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
553#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
554#[serde(transparent)]
555#[from(Arc<str>, String, &'static str)]
556#[non_exhaustive]
557pub struct AuthMethodId(pub Arc<str>);
558
559impl AuthMethodId {
560 #[must_use]
562 pub fn new(id: impl Into<Arc<str>>) -> Self {
563 Self(id.into())
564 }
565}
566
567#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
572#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
573#[serde(tag = "type", rename_all = "snake_case")]
574#[non_exhaustive]
575pub enum AuthMethod {
576 Terminal(AuthMethodTerminal),
579 #[serde(untagged)]
583 Agent(AuthMethodAgent),
584}
585
586impl AuthMethod {
587 #[must_use]
589 pub fn id(&self) -> &AuthMethodId {
590 match self {
591 Self::Agent(a) => &a.id,
592 Self::Terminal(t) => &t.id,
593 }
594 }
595
596 #[must_use]
598 pub fn name(&self) -> &str {
599 match self {
600 Self::Agent(a) => &a.name,
601 Self::Terminal(t) => &t.name,
602 }
603 }
604
605 #[must_use]
607 pub fn description(&self) -> Option<&str> {
608 match self {
609 Self::Agent(a) => a.description.as_deref(),
610 Self::Terminal(t) => t.description.as_deref(),
611 }
612 }
613
614 #[must_use]
620 pub fn meta(&self) -> Option<&Meta> {
621 match self {
622 Self::Agent(a) => a.meta.as_ref(),
623 Self::Terminal(t) => t.meta.as_ref(),
624 }
625 }
626}
627
628#[serde_as]
632#[skip_serializing_none]
633#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
634#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
635#[serde(rename_all = "camelCase")]
636#[non_exhaustive]
637pub struct AuthMethodAgent {
638 pub id: AuthMethodId,
640 pub name: String,
642 #[serde_as(deserialize_as = "DefaultOnError")]
644 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
645 #[serde(default)]
646 pub description: Option<String>,
647 #[serde_as(deserialize_as = "DefaultOnError")]
653 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
654 #[serde(default)]
655 #[serde(rename = "_meta")]
656 pub meta: Option<Meta>,
657}
658
659impl AuthMethodAgent {
660 #[must_use]
662 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
663 Self {
664 id: id.into(),
665 name: name.into(),
666 description: None,
667 meta: None,
668 }
669 }
670
671 #[must_use]
673 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
674 self.description = description.into_option();
675 self
676 }
677
678 #[must_use]
684 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
685 self.meta = meta.into_option();
686 self
687 }
688}
689
690#[serde_as]
698#[skip_serializing_none]
699#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
700#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
701#[serde(rename_all = "camelCase")]
702#[non_exhaustive]
703pub struct AuthMethodTerminal {
704 pub id: AuthMethodId,
706 pub name: String,
708 #[serde_as(deserialize_as = "DefaultOnError")]
710 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
711 #[serde(default)]
712 pub description: Option<String>,
713 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
715 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
716 #[serde(default, skip_serializing_if = "Vec::is_empty")]
717 pub args: Vec<String>,
718 #[serde_as(deserialize_as = "DefaultOnError")]
721 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
722 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
723 pub env: HashMap<String, String>,
724 #[serde_as(deserialize_as = "DefaultOnError")]
730 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
731 #[serde(default)]
732 #[serde(rename = "_meta")]
733 pub meta: Option<Meta>,
734}
735
736impl AuthMethodTerminal {
737 #[must_use]
739 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
740 Self {
741 id: id.into(),
742 name: name.into(),
743 description: None,
744 args: Vec::new(),
745 env: HashMap::new(),
746 meta: None,
747 }
748 }
749
750 #[must_use]
752 pub fn args(mut self, args: Vec<String>) -> Self {
753 self.args = args;
754 self
755 }
756
757 #[must_use]
760 pub fn env(mut self, env: HashMap<String, String>) -> Self {
761 self.env = env;
762 self
763 }
764
765 #[must_use]
767 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
768 self.description = description.into_option();
769 self
770 }
771
772 #[must_use]
778 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
779 self.meta = meta.into_option();
780 self
781 }
782}
783
784#[serde_as]
790#[skip_serializing_none]
791#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
792#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
793#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
794#[serde(rename_all = "camelCase")]
795#[non_exhaustive]
796pub struct NewSessionRequest {
797 pub cwd: PathBuf,
799 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
805 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
806 #[serde(default, skip_serializing_if = "Vec::is_empty")]
807 pub additional_directories: Vec<PathBuf>,
808 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
810 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
811 pub mcp_servers: Vec<McpServer>,
812 #[serde_as(deserialize_as = "DefaultOnError")]
818 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
819 #[serde(default)]
820 #[serde(rename = "_meta")]
821 pub meta: Option<Meta>,
822}
823
824impl NewSessionRequest {
825 #[must_use]
827 pub fn new(cwd: impl Into<PathBuf>) -> Self {
828 Self {
829 cwd: cwd.into(),
830 additional_directories: vec![],
831 mcp_servers: vec![],
832 meta: None,
833 }
834 }
835
836 #[must_use]
838 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
839 self.additional_directories = additional_directories;
840 self
841 }
842
843 #[must_use]
845 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
846 self.mcp_servers = mcp_servers;
847 self
848 }
849
850 #[must_use]
856 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
857 self.meta = meta.into_option();
858 self
859 }
860}
861
862#[serde_as]
866#[skip_serializing_none]
867#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
868#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
869#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME)))]
870#[serde(rename_all = "camelCase")]
871#[non_exhaustive]
872pub struct NewSessionResponse {
873 pub session_id: SessionId,
877 #[serde_as(deserialize_as = "DefaultOnError")]
881 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
882 #[serde(default)]
883 pub modes: Option<SessionModeState>,
884 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
886 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
887 #[serde(default)]
888 pub config_options: Option<Vec<SessionConfigOption>>,
889 #[serde_as(deserialize_as = "DefaultOnError")]
895 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
896 #[serde(default)]
897 #[serde(rename = "_meta")]
898 pub meta: Option<Meta>,
899}
900
901impl NewSessionResponse {
902 #[must_use]
904 pub fn new(session_id: impl Into<SessionId>) -> Self {
905 Self {
906 session_id: session_id.into(),
907 modes: None,
908 config_options: None,
909 meta: None,
910 }
911 }
912
913 #[must_use]
917 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
918 self.modes = modes.into_option();
919 self
920 }
921
922 #[must_use]
924 pub fn config_options(
925 mut self,
926 config_options: impl IntoOption<Vec<SessionConfigOption>>,
927 ) -> Self {
928 self.config_options = config_options.into_option();
929 self
930 }
931
932 #[must_use]
938 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
939 self.meta = meta.into_option();
940 self
941 }
942}
943
944#[serde_as]
952#[skip_serializing_none]
953#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
954#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
955#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
956#[serde(rename_all = "camelCase")]
957#[non_exhaustive]
958pub struct LoadSessionRequest {
959 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
961 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
962 pub mcp_servers: Vec<McpServer>,
963 pub cwd: PathBuf,
965 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
972 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
973 #[serde(default, skip_serializing_if = "Vec::is_empty")]
974 pub additional_directories: Vec<PathBuf>,
975 pub session_id: SessionId,
977 #[serde_as(deserialize_as = "DefaultOnError")]
983 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
984 #[serde(default)]
985 #[serde(rename = "_meta")]
986 pub meta: Option<Meta>,
987}
988
989impl LoadSessionRequest {
990 #[must_use]
992 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
993 Self {
994 mcp_servers: vec![],
995 cwd: cwd.into(),
996 additional_directories: vec![],
997 session_id: session_id.into(),
998 meta: None,
999 }
1000 }
1001
1002 #[must_use]
1004 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1005 self.additional_directories = additional_directories;
1006 self
1007 }
1008
1009 #[must_use]
1011 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1012 self.mcp_servers = mcp_servers;
1013 self
1014 }
1015
1016 #[must_use]
1022 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1023 self.meta = meta.into_option();
1024 self
1025 }
1026}
1027
1028#[serde_as]
1030#[skip_serializing_none]
1031#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1032#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1033#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME)))]
1034#[serde(rename_all = "camelCase")]
1035#[non_exhaustive]
1036pub struct LoadSessionResponse {
1037 #[serde_as(deserialize_as = "DefaultOnError")]
1041 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1042 #[serde(default)]
1043 pub modes: Option<SessionModeState>,
1044 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1046 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1047 #[serde(default)]
1048 pub config_options: Option<Vec<SessionConfigOption>>,
1049 #[serde_as(deserialize_as = "DefaultOnError")]
1055 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1056 #[serde(default)]
1057 #[serde(rename = "_meta")]
1058 pub meta: Option<Meta>,
1059}
1060
1061impl LoadSessionResponse {
1062 #[must_use]
1064 pub fn new() -> Self {
1065 Self::default()
1066 }
1067
1068 #[must_use]
1072 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1073 self.modes = modes.into_option();
1074 self
1075 }
1076
1077 #[must_use]
1079 pub fn config_options(
1080 mut self,
1081 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1082 ) -> Self {
1083 self.config_options = config_options.into_option();
1084 self
1085 }
1086
1087 #[must_use]
1093 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1094 self.meta = meta.into_option();
1095 self
1096 }
1097}
1098
1099#[cfg(feature = "unstable_session_fork")]
1112#[serde_as]
1113#[skip_serializing_none]
1114#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1115#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1116#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1117#[serde(rename_all = "camelCase")]
1118#[non_exhaustive]
1119pub struct ForkSessionRequest {
1120 pub session_id: SessionId,
1122 pub cwd: PathBuf,
1124 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1130 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1131 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1132 pub additional_directories: Vec<PathBuf>,
1133 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1135 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1136 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1137 pub mcp_servers: Vec<McpServer>,
1138 #[serde_as(deserialize_as = "DefaultOnError")]
1144 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1145 #[serde(default)]
1146 #[serde(rename = "_meta")]
1147 pub meta: Option<Meta>,
1148}
1149
1150#[cfg(feature = "unstable_session_fork")]
1151impl ForkSessionRequest {
1152 #[must_use]
1154 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1155 Self {
1156 session_id: session_id.into(),
1157 cwd: cwd.into(),
1158 additional_directories: vec![],
1159 mcp_servers: vec![],
1160 meta: None,
1161 }
1162 }
1163
1164 #[must_use]
1166 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1167 self.additional_directories = additional_directories;
1168 self
1169 }
1170
1171 #[must_use]
1173 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1174 self.mcp_servers = mcp_servers;
1175 self
1176 }
1177
1178 #[must_use]
1184 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1185 self.meta = meta.into_option();
1186 self
1187 }
1188}
1189
1190#[cfg(feature = "unstable_session_fork")]
1196#[serde_as]
1197#[skip_serializing_none]
1198#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1199#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1200#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME)))]
1201#[serde(rename_all = "camelCase")]
1202#[non_exhaustive]
1203pub struct ForkSessionResponse {
1204 pub session_id: SessionId,
1206 #[serde_as(deserialize_as = "DefaultOnError")]
1210 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1211 #[serde(default)]
1212 pub modes: Option<SessionModeState>,
1213 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1215 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1216 #[serde(default)]
1217 pub config_options: Option<Vec<SessionConfigOption>>,
1218 #[serde_as(deserialize_as = "DefaultOnError")]
1224 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1225 #[serde(default)]
1226 #[serde(rename = "_meta")]
1227 pub meta: Option<Meta>,
1228}
1229
1230#[cfg(feature = "unstable_session_fork")]
1231impl ForkSessionResponse {
1232 #[must_use]
1234 pub fn new(session_id: impl Into<SessionId>) -> Self {
1235 Self {
1236 session_id: session_id.into(),
1237 modes: None,
1238 config_options: None,
1239 meta: None,
1240 }
1241 }
1242
1243 #[must_use]
1247 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1248 self.modes = modes.into_option();
1249 self
1250 }
1251
1252 #[must_use]
1254 pub fn config_options(
1255 mut self,
1256 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1257 ) -> Self {
1258 self.config_options = config_options.into_option();
1259 self
1260 }
1261
1262 #[must_use]
1268 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1269 self.meta = meta.into_option();
1270 self
1271 }
1272}
1273
1274#[serde_as]
1283#[skip_serializing_none]
1284#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1285#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1286#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1287#[serde(rename_all = "camelCase")]
1288#[non_exhaustive]
1289pub struct ResumeSessionRequest {
1290 pub session_id: SessionId,
1292 pub cwd: PathBuf,
1294 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1301 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1302 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1303 pub additional_directories: Vec<PathBuf>,
1304 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1306 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1307 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1308 pub mcp_servers: Vec<McpServer>,
1309 #[serde_as(deserialize_as = "DefaultOnError")]
1315 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1316 #[serde(default)]
1317 #[serde(rename = "_meta")]
1318 pub meta: Option<Meta>,
1319}
1320
1321impl ResumeSessionRequest {
1322 #[must_use]
1324 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1325 Self {
1326 session_id: session_id.into(),
1327 cwd: cwd.into(),
1328 additional_directories: vec![],
1329 mcp_servers: vec![],
1330 meta: None,
1331 }
1332 }
1333
1334 #[must_use]
1336 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1337 self.additional_directories = additional_directories;
1338 self
1339 }
1340
1341 #[must_use]
1343 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1344 self.mcp_servers = mcp_servers;
1345 self
1346 }
1347
1348 #[must_use]
1354 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1355 self.meta = meta.into_option();
1356 self
1357 }
1358}
1359
1360#[serde_as]
1362#[skip_serializing_none]
1363#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1364#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1365#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME)))]
1366#[serde(rename_all = "camelCase")]
1367#[non_exhaustive]
1368pub struct ResumeSessionResponse {
1369 #[serde_as(deserialize_as = "DefaultOnError")]
1373 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1374 #[serde(default)]
1375 pub modes: Option<SessionModeState>,
1376 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1378 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1379 #[serde(default)]
1380 pub config_options: Option<Vec<SessionConfigOption>>,
1381 #[serde_as(deserialize_as = "DefaultOnError")]
1387 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1388 #[serde(default)]
1389 #[serde(rename = "_meta")]
1390 pub meta: Option<Meta>,
1391}
1392
1393impl ResumeSessionResponse {
1394 #[must_use]
1396 pub fn new() -> Self {
1397 Self::default()
1398 }
1399
1400 #[must_use]
1404 pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1405 self.modes = modes.into_option();
1406 self
1407 }
1408
1409 #[must_use]
1411 pub fn config_options(
1412 mut self,
1413 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1414 ) -> Self {
1415 self.config_options = config_options.into_option();
1416 self
1417 }
1418
1419 #[must_use]
1425 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1426 self.meta = meta.into_option();
1427 self
1428 }
1429}
1430
1431#[serde_as]
1441#[skip_serializing_none]
1442#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1443#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1444#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1445#[serde(rename_all = "camelCase")]
1446#[non_exhaustive]
1447pub struct CloseSessionRequest {
1448 pub session_id: SessionId,
1450 #[serde_as(deserialize_as = "DefaultOnError")]
1456 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1457 #[serde(default)]
1458 #[serde(rename = "_meta")]
1459 pub meta: Option<Meta>,
1460}
1461
1462impl CloseSessionRequest {
1463 #[must_use]
1465 pub fn new(session_id: impl Into<SessionId>) -> Self {
1466 Self {
1467 session_id: session_id.into(),
1468 meta: None,
1469 }
1470 }
1471
1472 #[must_use]
1478 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1479 self.meta = meta.into_option();
1480 self
1481 }
1482}
1483
1484#[serde_as]
1486#[skip_serializing_none]
1487#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1488#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1489#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME)))]
1490#[serde(rename_all = "camelCase")]
1491#[non_exhaustive]
1492pub struct CloseSessionResponse {
1493 #[serde_as(deserialize_as = "DefaultOnError")]
1499 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1500 #[serde(default)]
1501 #[serde(rename = "_meta")]
1502 pub meta: Option<Meta>,
1503}
1504
1505impl CloseSessionResponse {
1506 #[must_use]
1508 pub fn new() -> Self {
1509 Self::default()
1510 }
1511
1512 #[must_use]
1518 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1519 self.meta = meta.into_option();
1520 self
1521 }
1522}
1523
1524#[serde_as]
1530#[skip_serializing_none]
1531#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1532#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1533#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
1534#[serde(rename_all = "camelCase")]
1535#[non_exhaustive]
1536pub struct ListSessionsRequest {
1537 #[serde(default)]
1539 pub cwd: Option<PathBuf>,
1540 #[serde(default)]
1542 pub cursor: Option<String>,
1543 #[serde_as(deserialize_as = "DefaultOnError")]
1549 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1550 #[serde(default)]
1551 #[serde(rename = "_meta")]
1552 pub meta: Option<Meta>,
1553}
1554
1555impl ListSessionsRequest {
1556 #[must_use]
1558 pub fn new() -> Self {
1559 Self::default()
1560 }
1561
1562 #[must_use]
1564 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1565 self.cwd = cwd.into_option();
1566 self
1567 }
1568
1569 #[must_use]
1571 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1572 self.cursor = cursor.into_option();
1573 self
1574 }
1575
1576 #[must_use]
1582 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1583 self.meta = meta.into_option();
1584 self
1585 }
1586}
1587
1588#[serde_as]
1590#[skip_serializing_none]
1591#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1592#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1593#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME)))]
1594#[serde(rename_all = "camelCase")]
1595#[non_exhaustive]
1596pub struct ListSessionsResponse {
1597 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1599 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1600 pub sessions: Vec<SessionInfo>,
1601 #[serde_as(deserialize_as = "DefaultOnError")]
1604 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1605 #[serde(default)]
1606 pub next_cursor: Option<String>,
1607 #[serde_as(deserialize_as = "DefaultOnError")]
1613 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1614 #[serde(default)]
1615 #[serde(rename = "_meta")]
1616 pub meta: Option<Meta>,
1617}
1618
1619impl ListSessionsResponse {
1620 #[must_use]
1622 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1623 Self {
1624 sessions,
1625 next_cursor: None,
1626 meta: None,
1627 }
1628 }
1629
1630 #[must_use]
1632 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1633 self.next_cursor = next_cursor.into_option();
1634 self
1635 }
1636
1637 #[must_use]
1643 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1644 self.meta = meta.into_option();
1645 self
1646 }
1647}
1648
1649#[serde_as]
1655#[skip_serializing_none]
1656#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1657#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1658#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
1659#[serde(rename_all = "camelCase")]
1660#[non_exhaustive]
1661pub struct DeleteSessionRequest {
1662 pub session_id: SessionId,
1664 #[serde_as(deserialize_as = "DefaultOnError")]
1670 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1671 #[serde(default)]
1672 #[serde(rename = "_meta")]
1673 pub meta: Option<Meta>,
1674}
1675
1676impl DeleteSessionRequest {
1677 #[must_use]
1679 pub fn new(session_id: impl Into<SessionId>) -> Self {
1680 Self {
1681 session_id: session_id.into(),
1682 meta: None,
1683 }
1684 }
1685
1686 #[must_use]
1692 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1693 self.meta = meta.into_option();
1694 self
1695 }
1696}
1697
1698#[serde_as]
1700#[skip_serializing_none]
1701#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1702#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1703#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME)))]
1704#[serde(rename_all = "camelCase")]
1705#[non_exhaustive]
1706pub struct DeleteSessionResponse {
1707 #[serde_as(deserialize_as = "DefaultOnError")]
1713 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1714 #[serde(default)]
1715 #[serde(rename = "_meta")]
1716 pub meta: Option<Meta>,
1717}
1718
1719impl DeleteSessionResponse {
1720 #[must_use]
1722 pub fn new() -> Self {
1723 Self::default()
1724 }
1725
1726 #[must_use]
1732 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1733 self.meta = meta.into_option();
1734 self
1735 }
1736}
1737
1738#[serde_as]
1740#[skip_serializing_none]
1741#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1742#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1743#[serde(rename_all = "camelCase")]
1744#[non_exhaustive]
1745pub struct SessionInfo {
1746 pub session_id: SessionId,
1748 pub cwd: PathBuf,
1750 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1756 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1757 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1758 pub additional_directories: Vec<PathBuf>,
1759
1760 #[serde_as(deserialize_as = "DefaultOnError")]
1762 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1763 #[serde(default)]
1764 pub title: Option<String>,
1765 #[serde_as(deserialize_as = "DefaultOnError")]
1767 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1768 #[serde(default)]
1769 pub updated_at: Option<String>,
1770 #[serde_as(deserialize_as = "DefaultOnError")]
1776 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1777 #[serde(default)]
1778 #[serde(rename = "_meta")]
1779 pub meta: Option<Meta>,
1780}
1781
1782impl SessionInfo {
1783 #[must_use]
1785 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1786 Self {
1787 session_id: session_id.into(),
1788 cwd: cwd.into(),
1789 additional_directories: vec![],
1790 title: None,
1791 updated_at: None,
1792 meta: None,
1793 }
1794 }
1795
1796 #[must_use]
1798 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1799 self.additional_directories = additional_directories;
1800 self
1801 }
1802
1803 #[must_use]
1805 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1806 self.title = title.into_option();
1807 self
1808 }
1809
1810 #[must_use]
1812 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1813 self.updated_at = updated_at.into_option();
1814 self
1815 }
1816
1817 #[must_use]
1823 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1824 self.meta = meta.into_option();
1825 self
1826 }
1827}
1828
1829#[serde_as]
1833#[skip_serializing_none]
1834#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1835#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1836#[serde(rename_all = "camelCase")]
1837#[non_exhaustive]
1838pub struct SessionModeState {
1839 pub current_mode_id: SessionModeId,
1841 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1843 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1844 pub available_modes: Vec<SessionMode>,
1845 #[serde_as(deserialize_as = "DefaultOnError")]
1851 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1852 #[serde(default)]
1853 #[serde(rename = "_meta")]
1854 pub meta: Option<Meta>,
1855}
1856
1857impl SessionModeState {
1858 #[must_use]
1860 pub fn new(
1861 current_mode_id: impl Into<SessionModeId>,
1862 available_modes: Vec<SessionMode>,
1863 ) -> Self {
1864 Self {
1865 current_mode_id: current_mode_id.into(),
1866 available_modes,
1867 meta: None,
1868 }
1869 }
1870
1871 #[must_use]
1877 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1878 self.meta = meta.into_option();
1879 self
1880 }
1881}
1882
1883#[serde_as]
1887#[skip_serializing_none]
1888#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1889#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1890#[serde(rename_all = "camelCase")]
1891#[non_exhaustive]
1892pub struct SessionMode {
1893 pub id: SessionModeId,
1895 pub name: String,
1897 #[serde_as(deserialize_as = "DefaultOnError")]
1899 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1900 #[serde(default)]
1901 pub description: Option<String>,
1902 #[serde_as(deserialize_as = "DefaultOnError")]
1908 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1909 #[serde(default)]
1910 #[serde(rename = "_meta")]
1911 pub meta: Option<Meta>,
1912}
1913
1914impl SessionMode {
1915 #[must_use]
1917 pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
1918 Self {
1919 id: id.into(),
1920 name: name.into(),
1921 description: None,
1922 meta: None,
1923 }
1924 }
1925
1926 #[must_use]
1928 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1929 self.description = description.into_option();
1930 self
1931 }
1932
1933 #[must_use]
1939 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1940 self.meta = meta.into_option();
1941 self
1942 }
1943}
1944
1945#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1947#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
1948#[serde(transparent)]
1949#[from(Arc<str>, String, &'static str)]
1950#[non_exhaustive]
1951pub struct SessionModeId(pub Arc<str>);
1952
1953impl SessionModeId {
1954 #[must_use]
1956 pub fn new(id: impl Into<Arc<str>>) -> Self {
1957 Self(id.into())
1958 }
1959}
1960
1961#[serde_as]
1963#[skip_serializing_none]
1964#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1965#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1966#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
1967#[serde(rename_all = "camelCase")]
1968#[non_exhaustive]
1969pub struct SetSessionModeRequest {
1970 pub session_id: SessionId,
1972 pub mode_id: SessionModeId,
1974 #[serde_as(deserialize_as = "DefaultOnError")]
1980 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1981 #[serde(default)]
1982 #[serde(rename = "_meta")]
1983 pub meta: Option<Meta>,
1984}
1985
1986impl SetSessionModeRequest {
1987 #[must_use]
1989 pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
1990 Self {
1991 session_id: session_id.into(),
1992 mode_id: mode_id.into(),
1993 meta: None,
1994 }
1995 }
1996
1997 #[must_use]
1999 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2000 self.meta = meta.into_option();
2001 self
2002 }
2003}
2004
2005#[serde_as]
2007#[skip_serializing_none]
2008#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2009#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2010#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME)))]
2011#[serde(rename_all = "camelCase")]
2012#[non_exhaustive]
2013pub struct SetSessionModeResponse {
2014 #[serde_as(deserialize_as = "DefaultOnError")]
2020 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2021 #[serde(default)]
2022 #[serde(rename = "_meta")]
2023 pub meta: Option<Meta>,
2024}
2025
2026impl SetSessionModeResponse {
2027 #[must_use]
2029 pub fn new() -> Self {
2030 Self::default()
2031 }
2032
2033 #[must_use]
2039 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2040 self.meta = meta.into_option();
2041 self
2042 }
2043}
2044
2045#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2049#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2050#[serde(transparent)]
2051#[from(Arc<str>, String, &'static str)]
2052#[non_exhaustive]
2053pub struct SessionConfigId(pub Arc<str>);
2054
2055impl SessionConfigId {
2056 #[must_use]
2058 pub fn new(id: impl Into<Arc<str>>) -> Self {
2059 Self(id.into())
2060 }
2061}
2062
2063#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2065#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2066#[serde(transparent)]
2067#[from(Arc<str>, String, &'static str)]
2068#[non_exhaustive]
2069pub struct SessionConfigValueId(pub Arc<str>);
2070
2071impl SessionConfigValueId {
2072 #[must_use]
2074 pub fn new(id: impl Into<Arc<str>>) -> Self {
2075 Self(id.into())
2076 }
2077}
2078
2079#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2081#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, From, Display)]
2082#[serde(transparent)]
2083#[from(Arc<str>, String, &'static str)]
2084#[non_exhaustive]
2085pub struct SessionConfigGroupId(pub Arc<str>);
2086
2087impl SessionConfigGroupId {
2088 #[must_use]
2090 pub fn new(id: impl Into<Arc<str>>) -> Self {
2091 Self(id.into())
2092 }
2093}
2094
2095#[serde_as]
2097#[skip_serializing_none]
2098#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2099#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2100#[serde(rename_all = "camelCase")]
2101#[non_exhaustive]
2102pub struct SessionConfigSelectOption {
2103 pub value: SessionConfigValueId,
2105 pub name: String,
2107 #[serde_as(deserialize_as = "DefaultOnError")]
2109 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2110 #[serde(default)]
2111 pub description: Option<String>,
2112 #[serde_as(deserialize_as = "DefaultOnError")]
2118 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2119 #[serde(default)]
2120 #[serde(rename = "_meta")]
2121 pub meta: Option<Meta>,
2122}
2123
2124impl SessionConfigSelectOption {
2125 #[must_use]
2127 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2128 Self {
2129 value: value.into(),
2130 name: name.into(),
2131 description: None,
2132 meta: None,
2133 }
2134 }
2135
2136 #[must_use]
2138 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2139 self.description = description.into_option();
2140 self
2141 }
2142
2143 #[must_use]
2149 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2150 self.meta = meta.into_option();
2151 self
2152 }
2153}
2154
2155#[serde_as]
2157#[skip_serializing_none]
2158#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2159#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2160#[serde(rename_all = "camelCase")]
2161#[non_exhaustive]
2162pub struct SessionConfigSelectGroup {
2163 pub group: SessionConfigGroupId,
2165 pub name: String,
2167 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2169 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2170 pub options: Vec<SessionConfigSelectOption>,
2171 #[serde_as(deserialize_as = "DefaultOnError")]
2177 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2178 #[serde(default)]
2179 #[serde(rename = "_meta")]
2180 pub meta: Option<Meta>,
2181}
2182
2183impl SessionConfigSelectGroup {
2184 #[must_use]
2186 pub fn new(
2187 group: impl Into<SessionConfigGroupId>,
2188 name: impl Into<String>,
2189 options: Vec<SessionConfigSelectOption>,
2190 ) -> Self {
2191 Self {
2192 group: group.into(),
2193 name: name.into(),
2194 options,
2195 meta: None,
2196 }
2197 }
2198
2199 #[must_use]
2205 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2206 self.meta = meta.into_option();
2207 self
2208 }
2209}
2210
2211#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2213#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2214#[serde(untagged)]
2215#[non_exhaustive]
2216pub enum SessionConfigSelectOptions {
2217 Ungrouped(Vec<SessionConfigSelectOption>),
2219 Grouped(Vec<SessionConfigSelectGroup>),
2221}
2222
2223impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2224 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2225 SessionConfigSelectOptions::Ungrouped(options)
2226 }
2227}
2228
2229impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2230 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2231 SessionConfigSelectOptions::Grouped(groups)
2232 }
2233}
2234
2235#[skip_serializing_none]
2237#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2238#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2239#[serde(rename_all = "camelCase")]
2240#[non_exhaustive]
2241pub struct SessionConfigSelect {
2242 pub current_value: SessionConfigValueId,
2244 pub options: SessionConfigSelectOptions,
2246}
2247
2248impl SessionConfigSelect {
2249 #[must_use]
2251 pub fn new(
2252 current_value: impl Into<SessionConfigValueId>,
2253 options: impl Into<SessionConfigSelectOptions>,
2254 ) -> Self {
2255 Self {
2256 current_value: current_value.into(),
2257 options: options.into(),
2258 }
2259 }
2260}
2261
2262#[skip_serializing_none]
2264#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2265#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2266#[serde(rename_all = "camelCase")]
2267#[non_exhaustive]
2268pub struct SessionConfigBoolean {
2269 pub current_value: bool,
2271}
2272
2273impl SessionConfigBoolean {
2274 #[must_use]
2276 pub fn new(current_value: bool) -> Self {
2277 Self { current_value }
2278 }
2279}
2280
2281#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2291#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2292#[serde(rename_all = "snake_case")]
2293#[non_exhaustive]
2294pub enum SessionConfigOptionCategory {
2295 Mode,
2297 Model,
2299 ModelConfig,
2301 ThoughtLevel,
2303 #[serde(untagged)]
2305 Other(String),
2306}
2307
2308#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2310#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2311#[serde(tag = "type", rename_all = "snake_case")]
2312#[cfg_attr(feature = "schemars", schemars(extend("discriminator" = {"propertyName": "type"})))]
2313#[non_exhaustive]
2314pub enum SessionConfigKind {
2315 Select(SessionConfigSelect),
2317 Boolean(SessionConfigBoolean),
2319}
2320
2321#[serde_as]
2323#[skip_serializing_none]
2324#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2325#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2326#[serde(rename_all = "camelCase")]
2327#[non_exhaustive]
2328pub struct SessionConfigOption {
2329 pub id: SessionConfigId,
2331 pub name: String,
2333 #[serde_as(deserialize_as = "DefaultOnError")]
2335 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2336 #[serde(default)]
2337 pub description: Option<String>,
2338 #[serde_as(deserialize_as = "DefaultOnError")]
2340 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2341 #[serde(default)]
2342 pub category: Option<SessionConfigOptionCategory>,
2343 #[serde(flatten)]
2345 pub kind: SessionConfigKind,
2346 #[serde_as(deserialize_as = "DefaultOnError")]
2352 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2353 #[serde(default)]
2354 #[serde(rename = "_meta")]
2355 pub meta: Option<Meta>,
2356}
2357
2358impl SessionConfigOption {
2359 #[must_use]
2361 pub fn new(
2362 id: impl Into<SessionConfigId>,
2363 name: impl Into<String>,
2364 kind: SessionConfigKind,
2365 ) -> Self {
2366 Self {
2367 id: id.into(),
2368 name: name.into(),
2369 description: None,
2370 category: None,
2371 kind,
2372 meta: None,
2373 }
2374 }
2375
2376 #[must_use]
2378 pub fn select(
2379 id: impl Into<SessionConfigId>,
2380 name: impl Into<String>,
2381 current_value: impl Into<SessionConfigValueId>,
2382 options: impl Into<SessionConfigSelectOptions>,
2383 ) -> Self {
2384 Self::new(
2385 id,
2386 name,
2387 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2388 )
2389 }
2390
2391 #[must_use]
2393 pub fn boolean(
2394 id: impl Into<SessionConfigId>,
2395 name: impl Into<String>,
2396 current_value: bool,
2397 ) -> Self {
2398 Self::new(
2399 id,
2400 name,
2401 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2402 )
2403 }
2404
2405 #[must_use]
2407 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2408 self.description = description.into_option();
2409 self
2410 }
2411
2412 #[must_use]
2414 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2415 self.category = category.into_option();
2416 self
2417 }
2418
2419 #[must_use]
2425 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2426 self.meta = meta.into_option();
2427 self
2428 }
2429}
2430
2431#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2442#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2443#[serde(tag = "type", rename_all = "snake_case")]
2444#[non_exhaustive]
2445pub enum SessionConfigOptionValue {
2446 Boolean {
2448 value: bool,
2450 },
2451 #[serde(untagged)]
2457 ValueId {
2458 value: SessionConfigValueId,
2460 },
2461}
2462
2463impl SessionConfigOptionValue {
2464 #[must_use]
2466 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2467 Self::ValueId { value: id.into() }
2468 }
2469
2470 #[must_use]
2472 pub fn boolean(val: bool) -> Self {
2473 Self::Boolean { value: val }
2474 }
2475
2476 #[must_use]
2479 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2480 match self {
2481 Self::ValueId { value } => Some(value),
2482 _ => None,
2483 }
2484 }
2485
2486 #[must_use]
2488 pub fn as_bool(&self) -> Option<bool> {
2489 match self {
2490 Self::Boolean { value } => Some(*value),
2491 _ => None,
2492 }
2493 }
2494}
2495
2496impl From<SessionConfigValueId> for SessionConfigOptionValue {
2497 fn from(value: SessionConfigValueId) -> Self {
2498 Self::ValueId { value }
2499 }
2500}
2501
2502impl From<bool> for SessionConfigOptionValue {
2503 fn from(value: bool) -> Self {
2504 Self::Boolean { value }
2505 }
2506}
2507
2508impl From<&str> for SessionConfigOptionValue {
2509 fn from(value: &str) -> Self {
2510 Self::ValueId {
2511 value: SessionConfigValueId::new(value),
2512 }
2513 }
2514}
2515
2516#[serde_as]
2518#[skip_serializing_none]
2519#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2520#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2521#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
2522#[serde(rename_all = "camelCase")]
2523#[non_exhaustive]
2524pub struct SetSessionConfigOptionRequest {
2525 pub session_id: SessionId,
2527 pub config_id: SessionConfigId,
2529 #[serde(flatten)]
2534 pub value: SessionConfigOptionValue,
2535 #[serde_as(deserialize_as = "DefaultOnError")]
2541 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2542 #[serde(default)]
2543 #[serde(rename = "_meta")]
2544 pub meta: Option<Meta>,
2545}
2546
2547impl SetSessionConfigOptionRequest {
2548 #[must_use]
2550 pub fn new(
2551 session_id: impl Into<SessionId>,
2552 config_id: impl Into<SessionConfigId>,
2553 value: impl Into<SessionConfigOptionValue>,
2554 ) -> Self {
2555 Self {
2556 session_id: session_id.into(),
2557 config_id: config_id.into(),
2558 value: value.into(),
2559 meta: None,
2560 }
2561 }
2562
2563 #[must_use]
2569 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2570 self.meta = meta.into_option();
2571 self
2572 }
2573}
2574
2575#[serde_as]
2577#[skip_serializing_none]
2578#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2579#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2580#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME)))]
2581#[serde(rename_all = "camelCase")]
2582#[non_exhaustive]
2583pub struct SetSessionConfigOptionResponse {
2584 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2586 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
2587 pub config_options: Vec<SessionConfigOption>,
2588 #[serde_as(deserialize_as = "DefaultOnError")]
2594 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2595 #[serde(default)]
2596 #[serde(rename = "_meta")]
2597 pub meta: Option<Meta>,
2598}
2599
2600impl SetSessionConfigOptionResponse {
2601 #[must_use]
2603 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2604 Self {
2605 config_options,
2606 meta: None,
2607 }
2608 }
2609
2610 #[must_use]
2616 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2617 self.meta = meta.into_option();
2618 self
2619 }
2620}
2621
2622#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2631#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2632#[serde(tag = "type", rename_all = "snake_case")]
2633#[non_exhaustive]
2634pub enum McpServer {
2635 Http(McpServerHttp),
2639 Sse(McpServerSse),
2643 #[cfg(feature = "unstable_mcp_over_acp")]
2652 Acp(McpServerAcp),
2653 #[serde(untagged)]
2657 Stdio(McpServerStdio),
2658}
2659
2660#[serde_as]
2662#[skip_serializing_none]
2663#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2664#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2665#[serde(rename_all = "camelCase")]
2666#[non_exhaustive]
2667pub struct McpServerHttp {
2668 pub name: String,
2670 pub url: String,
2672 pub headers: Vec<HttpHeader>,
2674 #[serde_as(deserialize_as = "DefaultOnError")]
2680 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2681 #[serde(default)]
2682 #[serde(rename = "_meta")]
2683 pub meta: Option<Meta>,
2684}
2685
2686impl McpServerHttp {
2687 #[must_use]
2689 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2690 Self {
2691 name: name.into(),
2692 url: url.into(),
2693 headers: Vec::new(),
2694 meta: None,
2695 }
2696 }
2697
2698 #[must_use]
2700 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2701 self.headers = headers;
2702 self
2703 }
2704
2705 #[must_use]
2711 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2712 self.meta = meta.into_option();
2713 self
2714 }
2715}
2716
2717#[serde_as]
2719#[skip_serializing_none]
2720#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2721#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2722#[serde(rename_all = "camelCase")]
2723#[non_exhaustive]
2724pub struct McpServerSse {
2725 pub name: String,
2727 pub url: String,
2729 pub headers: Vec<HttpHeader>,
2731 #[serde_as(deserialize_as = "DefaultOnError")]
2737 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2738 #[serde(default)]
2739 #[serde(rename = "_meta")]
2740 pub meta: Option<Meta>,
2741}
2742
2743impl McpServerSse {
2744 #[must_use]
2746 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2747 Self {
2748 name: name.into(),
2749 url: url.into(),
2750 headers: Vec::new(),
2751 meta: None,
2752 }
2753 }
2754
2755 #[must_use]
2757 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2758 self.headers = headers;
2759 self
2760 }
2761
2762 #[must_use]
2768 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2769 self.meta = meta.into_option();
2770 self
2771 }
2772}
2773
2774#[cfg(feature = "unstable_mcp_over_acp")]
2784#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2785#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
2786#[serde(transparent)]
2787#[from(Arc<str>, String, &'static str)]
2788#[non_exhaustive]
2789pub struct McpServerAcpId(pub Arc<str>);
2790
2791#[cfg(feature = "unstable_mcp_over_acp")]
2792impl McpServerAcpId {
2793 #[must_use]
2795 pub fn new(id: impl Into<Arc<str>>) -> Self {
2796 Self(id.into())
2797 }
2798}
2799
2800#[serde_as]
2809#[skip_serializing_none]
2810#[cfg(feature = "unstable_mcp_over_acp")]
2811#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2812#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2813#[serde(rename_all = "camelCase")]
2814#[non_exhaustive]
2815pub struct McpServerAcp {
2816 pub name: String,
2818 pub server_id: McpServerAcpId,
2823 #[serde_as(deserialize_as = "DefaultOnError")]
2829 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2830 #[serde(default)]
2831 #[serde(rename = "_meta")]
2832 pub meta: Option<Meta>,
2833}
2834
2835#[cfg(feature = "unstable_mcp_over_acp")]
2836impl McpServerAcp {
2837 #[must_use]
2839 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2840 Self {
2841 name: name.into(),
2842 server_id: id.into(),
2843 meta: None,
2844 }
2845 }
2846
2847 #[must_use]
2853 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2854 self.meta = meta.into_option();
2855 self
2856 }
2857}
2858
2859#[serde_as]
2861#[skip_serializing_none]
2862#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2863#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2864#[serde(rename_all = "camelCase")]
2865#[non_exhaustive]
2866pub struct McpServerStdio {
2867 pub name: String,
2869 pub command: PathBuf,
2871 pub args: Vec<String>,
2873 pub env: Vec<EnvVariable>,
2875 #[serde_as(deserialize_as = "DefaultOnError")]
2881 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2882 #[serde(default)]
2883 #[serde(rename = "_meta")]
2884 pub meta: Option<Meta>,
2885}
2886
2887impl McpServerStdio {
2888 #[must_use]
2890 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2891 Self {
2892 name: name.into(),
2893 command: command.into(),
2894 args: Vec::new(),
2895 env: Vec::new(),
2896 meta: None,
2897 }
2898 }
2899
2900 #[must_use]
2902 pub fn args(mut self, args: Vec<String>) -> Self {
2903 self.args = args;
2904 self
2905 }
2906
2907 #[must_use]
2909 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2910 self.env = env;
2911 self
2912 }
2913
2914 #[must_use]
2920 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2921 self.meta = meta.into_option();
2922 self
2923 }
2924}
2925
2926#[serde_as]
2928#[skip_serializing_none]
2929#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2930#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2931#[serde(rename_all = "camelCase")]
2932#[non_exhaustive]
2933pub struct EnvVariable {
2934 pub name: String,
2936 pub value: String,
2938 #[serde_as(deserialize_as = "DefaultOnError")]
2944 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2945 #[serde(default)]
2946 #[serde(rename = "_meta")]
2947 pub meta: Option<Meta>,
2948}
2949
2950impl EnvVariable {
2951 #[must_use]
2953 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2954 Self {
2955 name: name.into(),
2956 value: value.into(),
2957 meta: None,
2958 }
2959 }
2960
2961 #[must_use]
2967 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2968 self.meta = meta.into_option();
2969 self
2970 }
2971}
2972
2973#[serde_as]
2975#[skip_serializing_none]
2976#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2977#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2978#[serde(rename_all = "camelCase")]
2979#[non_exhaustive]
2980pub struct HttpHeader {
2981 pub name: String,
2983 pub value: String,
2985 #[serde_as(deserialize_as = "DefaultOnError")]
2991 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2992 #[serde(default)]
2993 #[serde(rename = "_meta")]
2994 pub meta: Option<Meta>,
2995}
2996
2997impl HttpHeader {
2998 #[must_use]
3000 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3001 Self {
3002 name: name.into(),
3003 value: value.into(),
3004 meta: None,
3005 }
3006 }
3007
3008 #[must_use]
3014 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3015 self.meta = meta.into_option();
3016 self
3017 }
3018}
3019
3020#[serde_as]
3028#[skip_serializing_none]
3029#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3030#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
3031#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
3032#[serde(rename_all = "camelCase")]
3033#[non_exhaustive]
3034pub struct PromptRequest {
3035 pub session_id: SessionId,
3037 pub prompt: Vec<ContentBlock>,
3051 #[serde_as(deserialize_as = "DefaultOnError")]
3057 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3058 #[serde(default)]
3059 #[serde(rename = "_meta")]
3060 pub meta: Option<Meta>,
3061}
3062
3063impl PromptRequest {
3064 #[must_use]
3066 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3067 Self {
3068 session_id: session_id.into(),
3069 prompt,
3070 meta: None,
3071 }
3072 }
3073
3074 #[must_use]
3080 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3081 self.meta = meta.into_option();
3082 self
3083 }
3084}
3085
3086#[serde_as]
3090#[skip_serializing_none]
3091#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3092#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3093#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME)))]
3094#[serde(rename_all = "camelCase")]
3095#[non_exhaustive]
3096pub struct PromptResponse {
3097 pub stop_reason: StopReason,
3099 #[cfg(feature = "unstable_end_turn_token_usage")]
3105 #[serde_as(deserialize_as = "DefaultOnError")]
3106 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3107 #[serde(default)]
3108 pub usage: Option<Usage>,
3109 #[serde_as(deserialize_as = "DefaultOnError")]
3115 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3116 #[serde(default)]
3117 #[serde(rename = "_meta")]
3118 pub meta: Option<Meta>,
3119}
3120
3121impl PromptResponse {
3122 #[must_use]
3124 pub fn new(stop_reason: StopReason) -> Self {
3125 Self {
3126 stop_reason,
3127 #[cfg(feature = "unstable_end_turn_token_usage")]
3128 usage: None,
3129 meta: None,
3130 }
3131 }
3132
3133 #[cfg(feature = "unstable_end_turn_token_usage")]
3139 #[must_use]
3140 pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
3141 self.usage = usage.into_option();
3142 self
3143 }
3144
3145 #[must_use]
3151 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3152 self.meta = meta.into_option();
3153 self
3154 }
3155}
3156
3157#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3161#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
3162#[serde(rename_all = "snake_case")]
3163#[non_exhaustive]
3164pub enum StopReason {
3165 EndTurn,
3167 MaxTokens,
3169 MaxTurnRequests,
3172 Refusal,
3176 Cancelled,
3183}
3184
3185#[cfg(feature = "unstable_end_turn_token_usage")]
3191#[serde_as]
3192#[skip_serializing_none]
3193#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3194#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3195#[serde(rename_all = "camelCase")]
3196#[non_exhaustive]
3197pub struct Usage {
3198 pub total_tokens: u64,
3200 pub input_tokens: u64,
3202 pub output_tokens: u64,
3204 #[serde_as(deserialize_as = "DefaultOnError")]
3206 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3207 #[serde(default)]
3208 pub thought_tokens: Option<u64>,
3209 #[serde_as(deserialize_as = "DefaultOnError")]
3211 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3212 #[serde(default)]
3213 pub cached_read_tokens: Option<u64>,
3214 #[serde_as(deserialize_as = "DefaultOnError")]
3216 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3217 #[serde(default)]
3218 pub cached_write_tokens: Option<u64>,
3219 #[serde_as(deserialize_as = "DefaultOnError")]
3225 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3226 #[serde(default)]
3227 #[serde(rename = "_meta")]
3228 pub meta: Option<Meta>,
3229}
3230
3231#[cfg(feature = "unstable_end_turn_token_usage")]
3232impl Usage {
3233 #[must_use]
3235 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3236 Self {
3237 total_tokens,
3238 input_tokens,
3239 output_tokens,
3240 thought_tokens: None,
3241 cached_read_tokens: None,
3242 cached_write_tokens: None,
3243 meta: None,
3244 }
3245 }
3246
3247 #[must_use]
3249 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3250 self.thought_tokens = thought_tokens.into_option();
3251 self
3252 }
3253
3254 #[must_use]
3256 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3257 self.cached_read_tokens = cached_read_tokens.into_option();
3258 self
3259 }
3260
3261 #[must_use]
3263 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3264 self.cached_write_tokens = cached_write_tokens.into_option();
3265 self
3266 }
3267
3268 #[must_use]
3274 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3275 self.meta = meta.into_option();
3276 self
3277 }
3278}
3279
3280#[cfg(feature = "unstable_llm_providers")]
3293#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3294#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3295#[serde(rename_all = "snake_case")]
3296#[non_exhaustive]
3297#[expect(clippy::doc_markdown)]
3298pub enum LlmProtocol {
3299 Anthropic,
3301 #[serde(rename = "openai")]
3303 OpenAi,
3304 Azure,
3306 Vertex,
3308 Bedrock,
3310 #[serde(untagged)]
3312 Other(String),
3313}
3314
3315#[cfg(feature = "unstable_llm_providers")]
3321#[serde_as]
3322#[skip_serializing_none]
3323#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3324#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3325#[serde(rename_all = "camelCase")]
3326#[non_exhaustive]
3327pub struct ProviderCurrentConfig {
3328 pub api_type: LlmProtocol,
3330 pub base_url: String,
3332 #[serde_as(deserialize_as = "DefaultOnError")]
3338 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3339 #[serde(default)]
3340 #[serde(rename = "_meta")]
3341 pub meta: Option<Meta>,
3342}
3343
3344#[cfg(feature = "unstable_llm_providers")]
3345impl ProviderCurrentConfig {
3346 #[must_use]
3348 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3349 Self {
3350 api_type,
3351 base_url: base_url.into(),
3352 meta: None,
3353 }
3354 }
3355
3356 #[must_use]
3362 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3363 self.meta = meta.into_option();
3364 self
3365 }
3366}
3367
3368#[cfg(feature = "unstable_llm_providers")]
3374#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3375#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
3376#[serde(transparent)]
3377#[from(Arc<str>, String, &'static str)]
3378#[non_exhaustive]
3379pub struct ProviderId(pub Arc<str>);
3380
3381#[cfg(feature = "unstable_llm_providers")]
3382impl ProviderId {
3383 #[must_use]
3385 pub fn new(id: impl Into<Arc<str>>) -> Self {
3386 Self(id.into())
3387 }
3388}
3389
3390#[cfg(feature = "unstable_llm_providers")]
3396#[serde_as]
3397#[skip_serializing_none]
3398#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3399#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3400#[serde(rename_all = "camelCase")]
3401#[non_exhaustive]
3402pub struct ProviderInfo {
3403 pub provider_id: ProviderId,
3405 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3407 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
3408 pub supported: Vec<LlmProtocol>,
3409 pub required: bool,
3412 #[serde(default)]
3415 pub current: Option<ProviderCurrentConfig>,
3416 #[serde_as(deserialize_as = "DefaultOnError")]
3422 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3423 #[serde(default)]
3424 #[serde(rename = "_meta")]
3425 pub meta: Option<Meta>,
3426}
3427
3428#[cfg(feature = "unstable_llm_providers")]
3429impl ProviderInfo {
3430 #[must_use]
3432 pub fn new(
3433 provider_id: impl Into<ProviderId>,
3434 supported: Vec<LlmProtocol>,
3435 required: bool,
3436 current: impl IntoOption<ProviderCurrentConfig>,
3437 ) -> Self {
3438 Self {
3439 provider_id: provider_id.into(),
3440 supported,
3441 required,
3442 current: current.into_option(),
3443 meta: None,
3444 }
3445 }
3446
3447 #[must_use]
3453 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3454 self.meta = meta.into_option();
3455 self
3456 }
3457}
3458
3459#[cfg(feature = "unstable_llm_providers")]
3465#[serde_as]
3466#[skip_serializing_none]
3467#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3468#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3469#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
3470#[serde(rename_all = "camelCase")]
3471#[non_exhaustive]
3472pub struct ListProvidersRequest {
3473 #[serde_as(deserialize_as = "DefaultOnError")]
3479 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3480 #[serde(default)]
3481 #[serde(rename = "_meta")]
3482 pub meta: Option<Meta>,
3483}
3484
3485#[cfg(feature = "unstable_llm_providers")]
3486impl ListProvidersRequest {
3487 #[must_use]
3489 pub fn new() -> Self {
3490 Self::default()
3491 }
3492
3493 #[must_use]
3499 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3500 self.meta = meta.into_option();
3501 self
3502 }
3503}
3504
3505#[cfg(feature = "unstable_llm_providers")]
3511#[serde_as]
3512#[skip_serializing_none]
3513#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3514#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3515#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME)))]
3516#[serde(rename_all = "camelCase")]
3517#[non_exhaustive]
3518pub struct ListProvidersResponse {
3519 pub providers: Vec<ProviderInfo>,
3521 #[serde_as(deserialize_as = "DefaultOnError")]
3527 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3528 #[serde(default)]
3529 #[serde(rename = "_meta")]
3530 pub meta: Option<Meta>,
3531}
3532
3533#[cfg(feature = "unstable_llm_providers")]
3534impl ListProvidersResponse {
3535 #[must_use]
3537 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3538 Self {
3539 providers,
3540 meta: None,
3541 }
3542 }
3543
3544 #[must_use]
3550 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3551 self.meta = meta.into_option();
3552 self
3553 }
3554}
3555
3556#[cfg(feature = "unstable_llm_providers")]
3564#[serde_as]
3565#[skip_serializing_none]
3566#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3567#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
3568#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
3569#[serde(rename_all = "camelCase")]
3570#[non_exhaustive]
3571pub struct SetProviderRequest {
3572 pub provider_id: ProviderId,
3574 pub api_type: LlmProtocol,
3576 pub base_url: String,
3578 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3581 pub headers: HashMap<String, String>,
3582 #[serde_as(deserialize_as = "DefaultOnError")]
3588 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3589 #[serde(default)]
3590 #[serde(rename = "_meta")]
3591 pub meta: Option<Meta>,
3592}
3593
3594#[cfg(feature = "unstable_llm_providers")]
3595impl SetProviderRequest {
3596 #[must_use]
3598 pub fn new(
3599 provider_id: impl Into<ProviderId>,
3600 api_type: LlmProtocol,
3601 base_url: impl Into<String>,
3602 ) -> Self {
3603 Self {
3604 provider_id: provider_id.into(),
3605 api_type,
3606 base_url: base_url.into(),
3607 headers: HashMap::new(),
3608 meta: None,
3609 }
3610 }
3611
3612 #[must_use]
3615 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3616 self.headers = headers;
3617 self
3618 }
3619
3620 #[must_use]
3626 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3627 self.meta = meta.into_option();
3628 self
3629 }
3630}
3631
3632#[cfg(feature = "unstable_llm_providers")]
3638#[serde_as]
3639#[skip_serializing_none]
3640#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3641#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3642#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME)))]
3643#[serde(rename_all = "camelCase")]
3644#[non_exhaustive]
3645pub struct SetProviderResponse {
3646 #[serde_as(deserialize_as = "DefaultOnError")]
3652 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3653 #[serde(default)]
3654 #[serde(rename = "_meta")]
3655 pub meta: Option<Meta>,
3656}
3657
3658#[cfg(feature = "unstable_llm_providers")]
3659impl SetProviderResponse {
3660 #[must_use]
3662 pub fn new() -> Self {
3663 Self::default()
3664 }
3665
3666 #[must_use]
3672 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3673 self.meta = meta.into_option();
3674 self
3675 }
3676}
3677
3678#[cfg(feature = "unstable_llm_providers")]
3684#[serde_as]
3685#[skip_serializing_none]
3686#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3687#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3688#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
3689#[serde(rename_all = "camelCase")]
3690#[non_exhaustive]
3691pub struct DisableProviderRequest {
3692 pub provider_id: ProviderId,
3694 #[serde_as(deserialize_as = "DefaultOnError")]
3700 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3701 #[serde(default)]
3702 #[serde(rename = "_meta")]
3703 pub meta: Option<Meta>,
3704}
3705
3706#[cfg(feature = "unstable_llm_providers")]
3707impl DisableProviderRequest {
3708 #[must_use]
3710 pub fn new(provider_id: impl Into<ProviderId>) -> Self {
3711 Self {
3712 provider_id: provider_id.into(),
3713 meta: None,
3714 }
3715 }
3716
3717 #[must_use]
3723 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3724 self.meta = meta.into_option();
3725 self
3726 }
3727}
3728
3729#[cfg(feature = "unstable_llm_providers")]
3735#[serde_as]
3736#[skip_serializing_none]
3737#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3738#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3739#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME)))]
3740#[serde(rename_all = "camelCase")]
3741#[non_exhaustive]
3742pub struct DisableProviderResponse {
3743 #[serde_as(deserialize_as = "DefaultOnError")]
3749 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3750 #[serde(default)]
3751 #[serde(rename = "_meta")]
3752 pub meta: Option<Meta>,
3753}
3754
3755#[cfg(feature = "unstable_llm_providers")]
3756impl DisableProviderResponse {
3757 #[must_use]
3759 pub fn new() -> Self {
3760 Self::default()
3761 }
3762
3763 #[must_use]
3769 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3770 self.meta = meta.into_option();
3771 self
3772 }
3773}
3774
3775#[serde_as]
3784#[skip_serializing_none]
3785#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3786#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3787#[serde(rename_all = "camelCase")]
3788#[non_exhaustive]
3789pub struct AgentCapabilities {
3790 #[serde_as(deserialize_as = "DefaultOnError")]
3792 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3793 #[serde(default)]
3794 pub load_session: bool,
3795 #[serde_as(deserialize_as = "DefaultOnError")]
3797 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3798 #[serde(default)]
3799 pub prompt_capabilities: PromptCapabilities,
3800 #[serde_as(deserialize_as = "DefaultOnError")]
3802 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3803 #[serde(default)]
3804 pub mcp_capabilities: McpCapabilities,
3805 #[serde_as(deserialize_as = "DefaultOnError")]
3807 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3808 #[serde(default)]
3809 pub session_capabilities: SessionCapabilities,
3810 #[serde_as(deserialize_as = "DefaultOnError")]
3812 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3813 #[serde(default)]
3814 pub auth: AgentAuthCapabilities,
3815 #[cfg(feature = "unstable_llm_providers")]
3824 #[serde_as(deserialize_as = "DefaultOnError")]
3825 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3826 #[serde(default)]
3827 pub providers: Option<ProvidersCapabilities>,
3828 #[cfg(feature = "unstable_nes")]
3837 #[serde_as(deserialize_as = "DefaultOnError")]
3838 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3839 #[serde(default)]
3840 pub nes: Option<NesCapabilities>,
3841 #[cfg(feature = "unstable_nes")]
3847 #[serde_as(deserialize_as = "DefaultOnError")]
3848 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3849 #[serde(default)]
3850 pub position_encoding: Option<PositionEncodingKind>,
3851 #[serde_as(deserialize_as = "DefaultOnError")]
3857 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3858 #[serde(default)]
3859 #[serde(rename = "_meta")]
3860 pub meta: Option<Meta>,
3861}
3862
3863impl AgentCapabilities {
3864 #[must_use]
3866 pub fn new() -> Self {
3867 Self::default()
3868 }
3869
3870 #[must_use]
3872 pub fn load_session(mut self, load_session: bool) -> Self {
3873 self.load_session = load_session;
3874 self
3875 }
3876
3877 #[must_use]
3879 pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
3880 self.prompt_capabilities = prompt_capabilities;
3881 self
3882 }
3883
3884 #[must_use]
3886 pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
3887 self.mcp_capabilities = mcp_capabilities;
3888 self
3889 }
3890
3891 #[must_use]
3893 pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
3894 self.session_capabilities = session_capabilities;
3895 self
3896 }
3897
3898 #[must_use]
3900 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
3901 self.auth = auth;
3902 self
3903 }
3904
3905 #[cfg(feature = "unstable_llm_providers")]
3911 #[must_use]
3912 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
3913 self.providers = providers.into_option();
3914 self
3915 }
3916
3917 #[cfg(feature = "unstable_nes")]
3923 #[must_use]
3924 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
3925 self.nes = nes.into_option();
3926 self
3927 }
3928
3929 #[cfg(feature = "unstable_nes")]
3933 #[must_use]
3934 pub fn position_encoding(
3935 mut self,
3936 position_encoding: impl IntoOption<PositionEncodingKind>,
3937 ) -> Self {
3938 self.position_encoding = position_encoding.into_option();
3939 self
3940 }
3941
3942 #[must_use]
3948 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3949 self.meta = meta.into_option();
3950 self
3951 }
3952}
3953
3954#[cfg(feature = "unstable_llm_providers")]
3962#[serde_as]
3963#[skip_serializing_none]
3964#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
3965#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3966#[non_exhaustive]
3967pub struct ProvidersCapabilities {
3968 #[serde_as(deserialize_as = "DefaultOnError")]
3974 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
3975 #[serde(default)]
3976 #[serde(rename = "_meta")]
3977 pub meta: Option<Meta>,
3978}
3979
3980#[cfg(feature = "unstable_llm_providers")]
3981impl ProvidersCapabilities {
3982 #[must_use]
3984 pub fn new() -> Self {
3985 Self::default()
3986 }
3987
3988 #[must_use]
3994 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3995 self.meta = meta.into_option();
3996 self
3997 }
3998}
3999
4000#[serde_as]
4010#[skip_serializing_none]
4011#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4012#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4013#[serde(rename_all = "camelCase")]
4014#[non_exhaustive]
4015pub struct SessionCapabilities {
4016 #[serde_as(deserialize_as = "DefaultOnError")]
4021 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4022 #[serde(default)]
4023 pub list: Option<SessionListCapabilities>,
4024 #[serde_as(deserialize_as = "DefaultOnError")]
4029 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4030 #[serde(default)]
4031 pub delete: Option<SessionDeleteCapabilities>,
4032 #[serde_as(deserialize_as = "DefaultOnError")]
4042 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4043 #[serde(default)]
4044 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
4045 #[cfg(feature = "unstable_session_fork")]
4054 #[serde_as(deserialize_as = "DefaultOnError")]
4055 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4056 #[serde(default)]
4057 pub fork: Option<SessionForkCapabilities>,
4058 #[serde_as(deserialize_as = "DefaultOnError")]
4063 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4064 #[serde(default)]
4065 pub resume: Option<SessionResumeCapabilities>,
4066 #[serde_as(deserialize_as = "DefaultOnError")]
4071 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4072 #[serde(default)]
4073 pub close: Option<SessionCloseCapabilities>,
4074 #[serde_as(deserialize_as = "DefaultOnError")]
4080 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4081 #[serde(default)]
4082 #[serde(rename = "_meta")]
4083 pub meta: Option<Meta>,
4084}
4085
4086impl SessionCapabilities {
4087 #[must_use]
4089 pub fn new() -> Self {
4090 Self::default()
4091 }
4092
4093 #[must_use]
4098 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
4099 self.list = list.into_option();
4100 self
4101 }
4102
4103 #[must_use]
4108 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4109 self.delete = delete.into_option();
4110 self
4111 }
4112
4113 #[must_use]
4123 pub fn additional_directories(
4124 mut self,
4125 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4126 ) -> Self {
4127 self.additional_directories = additional_directories.into_option();
4128 self
4129 }
4130
4131 #[cfg(feature = "unstable_session_fork")]
4132 #[must_use]
4137 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4138 self.fork = fork.into_option();
4139 self
4140 }
4141
4142 #[must_use]
4147 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4148 self.resume = resume.into_option();
4149 self
4150 }
4151
4152 #[must_use]
4157 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4158 self.close = close.into_option();
4159 self
4160 }
4161
4162 #[must_use]
4168 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4169 self.meta = meta.into_option();
4170 self
4171 }
4172}
4173
4174#[serde_as]
4178#[skip_serializing_none]
4179#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4180#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4181#[non_exhaustive]
4182pub struct SessionListCapabilities {
4183 #[serde_as(deserialize_as = "DefaultOnError")]
4189 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4190 #[serde(default)]
4191 #[serde(rename = "_meta")]
4192 pub meta: Option<Meta>,
4193}
4194
4195impl SessionListCapabilities {
4196 #[must_use]
4198 pub fn new() -> Self {
4199 Self::default()
4200 }
4201
4202 #[must_use]
4208 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4209 self.meta = meta.into_option();
4210 self
4211 }
4212}
4213
4214#[serde_as]
4218#[skip_serializing_none]
4219#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4220#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4221#[non_exhaustive]
4222pub struct SessionDeleteCapabilities {
4223 #[serde_as(deserialize_as = "DefaultOnError")]
4229 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4230 #[serde(default)]
4231 #[serde(rename = "_meta")]
4232 pub meta: Option<Meta>,
4233}
4234
4235impl SessionDeleteCapabilities {
4236 #[must_use]
4238 pub fn new() -> Self {
4239 Self::default()
4240 }
4241
4242 #[must_use]
4248 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4249 self.meta = meta.into_option();
4250 self
4251 }
4252}
4253
4254#[serde_as]
4261#[skip_serializing_none]
4262#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4263#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4264#[non_exhaustive]
4265pub struct SessionAdditionalDirectoriesCapabilities {
4266 #[serde_as(deserialize_as = "DefaultOnError")]
4272 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4273 #[serde(default)]
4274 #[serde(rename = "_meta")]
4275 pub meta: Option<Meta>,
4276}
4277
4278impl SessionAdditionalDirectoriesCapabilities {
4279 #[must_use]
4281 pub fn new() -> Self {
4282 Self::default()
4283 }
4284
4285 #[must_use]
4291 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4292 self.meta = meta.into_option();
4293 self
4294 }
4295}
4296
4297#[cfg(feature = "unstable_session_fork")]
4305#[serde_as]
4306#[skip_serializing_none]
4307#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4308#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4309#[non_exhaustive]
4310pub struct SessionForkCapabilities {
4311 #[serde_as(deserialize_as = "DefaultOnError")]
4317 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4318 #[serde(default)]
4319 #[serde(rename = "_meta")]
4320 pub meta: Option<Meta>,
4321}
4322
4323#[cfg(feature = "unstable_session_fork")]
4324impl SessionForkCapabilities {
4325 #[must_use]
4327 pub fn new() -> Self {
4328 Self::default()
4329 }
4330
4331 #[must_use]
4337 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4338 self.meta = meta.into_option();
4339 self
4340 }
4341}
4342
4343#[serde_as]
4347#[skip_serializing_none]
4348#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4349#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4350#[non_exhaustive]
4351pub struct SessionResumeCapabilities {
4352 #[serde_as(deserialize_as = "DefaultOnError")]
4358 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4359 #[serde(default)]
4360 #[serde(rename = "_meta")]
4361 pub meta: Option<Meta>,
4362}
4363
4364impl SessionResumeCapabilities {
4365 #[must_use]
4367 pub fn new() -> Self {
4368 Self::default()
4369 }
4370
4371 #[must_use]
4377 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4378 self.meta = meta.into_option();
4379 self
4380 }
4381}
4382
4383#[serde_as]
4387#[skip_serializing_none]
4388#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4389#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4390#[non_exhaustive]
4391pub struct SessionCloseCapabilities {
4392 #[serde_as(deserialize_as = "DefaultOnError")]
4398 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4399 #[serde(default)]
4400 #[serde(rename = "_meta")]
4401 pub meta: Option<Meta>,
4402}
4403
4404impl SessionCloseCapabilities {
4405 #[must_use]
4407 pub fn new() -> Self {
4408 Self::default()
4409 }
4410
4411 #[must_use]
4417 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4418 self.meta = meta.into_option();
4419 self
4420 }
4421}
4422
4423#[serde_as]
4436#[skip_serializing_none]
4437#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4438#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4439#[serde(rename_all = "camelCase")]
4440#[non_exhaustive]
4441pub struct PromptCapabilities {
4442 #[serde_as(deserialize_as = "DefaultOnError")]
4444 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4445 #[serde(default)]
4446 pub image: bool,
4447 #[serde_as(deserialize_as = "DefaultOnError")]
4449 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4450 #[serde(default)]
4451 pub audio: bool,
4452 #[serde_as(deserialize_as = "DefaultOnError")]
4457 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4458 #[serde(default)]
4459 pub embedded_context: bool,
4460 #[serde_as(deserialize_as = "DefaultOnError")]
4466 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4467 #[serde(default)]
4468 #[serde(rename = "_meta")]
4469 pub meta: Option<Meta>,
4470}
4471
4472impl PromptCapabilities {
4473 #[must_use]
4475 pub fn new() -> Self {
4476 Self::default()
4477 }
4478
4479 #[must_use]
4481 pub fn image(mut self, image: bool) -> Self {
4482 self.image = image;
4483 self
4484 }
4485
4486 #[must_use]
4488 pub fn audio(mut self, audio: bool) -> Self {
4489 self.audio = audio;
4490 self
4491 }
4492
4493 #[must_use]
4498 pub fn embedded_context(mut self, embedded_context: bool) -> Self {
4499 self.embedded_context = embedded_context;
4500 self
4501 }
4502
4503 #[must_use]
4509 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4510 self.meta = meta.into_option();
4511 self
4512 }
4513}
4514
4515#[serde_as]
4517#[skip_serializing_none]
4518#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4519#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4520#[serde(rename_all = "camelCase")]
4521#[non_exhaustive]
4522pub struct McpCapabilities {
4523 #[serde_as(deserialize_as = "DefaultOnError")]
4525 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4526 #[serde(default)]
4527 pub http: bool,
4528 #[serde_as(deserialize_as = "DefaultOnError")]
4530 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4531 #[serde(default)]
4532 pub sse: bool,
4533 #[cfg(feature = "unstable_mcp_over_acp")]
4539 #[serde_as(deserialize_as = "DefaultOnError")]
4540 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4541 #[serde(default)]
4542 pub acp: bool,
4543 #[serde_as(deserialize_as = "DefaultOnError")]
4549 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
4550 #[serde(default)]
4551 #[serde(rename = "_meta")]
4552 pub meta: Option<Meta>,
4553}
4554
4555impl McpCapabilities {
4556 #[must_use]
4558 pub fn new() -> Self {
4559 Self::default()
4560 }
4561
4562 #[must_use]
4564 pub fn http(mut self, http: bool) -> Self {
4565 self.http = http;
4566 self
4567 }
4568
4569 #[must_use]
4571 pub fn sse(mut self, sse: bool) -> Self {
4572 self.sse = sse;
4573 self
4574 }
4575
4576 #[cfg(feature = "unstable_mcp_over_acp")]
4582 #[must_use]
4583 pub fn acp(mut self, acp: bool) -> Self {
4584 self.acp = acp;
4585 self
4586 }
4587
4588 #[must_use]
4594 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4595 self.meta = meta.into_option();
4596 self
4597 }
4598}
4599
4600#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4606#[non_exhaustive]
4607pub struct AgentMethodNames {
4608 pub initialize: &'static str,
4610 pub authenticate: &'static str,
4612 #[cfg(feature = "unstable_llm_providers")]
4614 pub providers_list: &'static str,
4615 #[cfg(feature = "unstable_llm_providers")]
4617 pub providers_set: &'static str,
4618 #[cfg(feature = "unstable_llm_providers")]
4620 pub providers_disable: &'static str,
4621 pub session_new: &'static str,
4623 pub session_load: &'static str,
4625 pub session_set_mode: &'static str,
4627 pub session_set_config_option: &'static str,
4629 pub session_prompt: &'static str,
4631 pub session_cancel: &'static str,
4633 #[cfg(feature = "unstable_mcp_over_acp")]
4635 pub mcp_message: &'static str,
4636 pub session_list: &'static str,
4638 pub session_delete: &'static str,
4640 #[cfg(feature = "unstable_session_fork")]
4642 pub session_fork: &'static str,
4643 pub session_resume: &'static str,
4645 pub session_close: &'static str,
4647 pub logout: &'static str,
4649 #[cfg(feature = "unstable_nes")]
4651 pub nes_start: &'static str,
4652 #[cfg(feature = "unstable_nes")]
4654 pub nes_suggest: &'static str,
4655 #[cfg(feature = "unstable_nes")]
4657 pub nes_accept: &'static str,
4658 #[cfg(feature = "unstable_nes")]
4660 pub nes_reject: &'static str,
4661 #[cfg(feature = "unstable_nes")]
4663 pub nes_close: &'static str,
4664 #[cfg(feature = "unstable_nes")]
4666 pub document_did_open: &'static str,
4667 #[cfg(feature = "unstable_nes")]
4669 pub document_did_change: &'static str,
4670 #[cfg(feature = "unstable_nes")]
4672 pub document_did_close: &'static str,
4673 #[cfg(feature = "unstable_nes")]
4675 pub document_did_save: &'static str,
4676 #[cfg(feature = "unstable_nes")]
4678 pub document_did_focus: &'static str,
4679}
4680
4681pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4683 initialize: INITIALIZE_METHOD_NAME,
4684 authenticate: AUTHENTICATE_METHOD_NAME,
4685 #[cfg(feature = "unstable_llm_providers")]
4686 providers_list: PROVIDERS_LIST_METHOD_NAME,
4687 #[cfg(feature = "unstable_llm_providers")]
4688 providers_set: PROVIDERS_SET_METHOD_NAME,
4689 #[cfg(feature = "unstable_llm_providers")]
4690 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4691 session_new: SESSION_NEW_METHOD_NAME,
4692 session_load: SESSION_LOAD_METHOD_NAME,
4693 session_set_mode: SESSION_SET_MODE_METHOD_NAME,
4694 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4695 session_prompt: SESSION_PROMPT_METHOD_NAME,
4696 session_cancel: SESSION_CANCEL_METHOD_NAME,
4697 #[cfg(feature = "unstable_mcp_over_acp")]
4698 mcp_message: MCP_MESSAGE_METHOD_NAME,
4699 session_list: SESSION_LIST_METHOD_NAME,
4700 session_delete: SESSION_DELETE_METHOD_NAME,
4701 #[cfg(feature = "unstable_session_fork")]
4702 session_fork: SESSION_FORK_METHOD_NAME,
4703 session_resume: SESSION_RESUME_METHOD_NAME,
4704 session_close: SESSION_CLOSE_METHOD_NAME,
4705 logout: LOGOUT_METHOD_NAME,
4706 #[cfg(feature = "unstable_nes")]
4707 nes_start: NES_START_METHOD_NAME,
4708 #[cfg(feature = "unstable_nes")]
4709 nes_suggest: NES_SUGGEST_METHOD_NAME,
4710 #[cfg(feature = "unstable_nes")]
4711 nes_accept: NES_ACCEPT_METHOD_NAME,
4712 #[cfg(feature = "unstable_nes")]
4713 nes_reject: NES_REJECT_METHOD_NAME,
4714 #[cfg(feature = "unstable_nes")]
4715 nes_close: NES_CLOSE_METHOD_NAME,
4716 #[cfg(feature = "unstable_nes")]
4717 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4718 #[cfg(feature = "unstable_nes")]
4719 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4720 #[cfg(feature = "unstable_nes")]
4721 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4722 #[cfg(feature = "unstable_nes")]
4723 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4724 #[cfg(feature = "unstable_nes")]
4725 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4726};
4727
4728pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4730pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4732#[cfg(feature = "unstable_llm_providers")]
4734pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4735#[cfg(feature = "unstable_llm_providers")]
4737pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4738#[cfg(feature = "unstable_llm_providers")]
4740pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4741pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4743pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4745pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
4747pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4749pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4751pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4753pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4755pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4757#[cfg(feature = "unstable_session_fork")]
4759pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4760pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4762pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4764pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4766
4767#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
4774#[derive(Clone, Debug, Serialize, Deserialize)]
4775#[serde(untagged)]
4776#[cfg_attr(feature = "schemars", schemars(inline))]
4777#[non_exhaustive]
4778#[allow(clippy::large_enum_variant)]
4779pub enum ClientRequest {
4780 InitializeRequest(InitializeRequest),
4791 AuthenticateRequest(AuthenticateRequest),
4802 #[cfg(feature = "unstable_llm_providers")]
4808 ListProvidersRequest(ListProvidersRequest),
4809 #[cfg(feature = "unstable_llm_providers")]
4815 SetProviderRequest(SetProviderRequest),
4816 #[cfg(feature = "unstable_llm_providers")]
4822 DisableProviderRequest(DisableProviderRequest),
4823 LogoutRequest(LogoutRequest),
4828 NewSessionRequest(NewSessionRequest),
4841 LoadSessionRequest(LoadSessionRequest),
4852 ListSessionsRequest(ListSessionsRequest),
4858 DeleteSessionRequest(DeleteSessionRequest),
4862 #[cfg(feature = "unstable_session_fork")]
4863 ForkSessionRequest(ForkSessionRequest),
4875 ResumeSessionRequest(ResumeSessionRequest),
4882 CloseSessionRequest(CloseSessionRequest),
4889 SetSessionModeRequest(SetSessionModeRequest),
4903 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
4905 PromptRequest(PromptRequest),
4917 #[cfg(feature = "unstable_nes")]
4918 StartNesRequest(StartNesRequest),
4924 #[cfg(feature = "unstable_nes")]
4925 SuggestNesRequest(SuggestNesRequest),
4931 #[cfg(feature = "unstable_nes")]
4932 CloseNesRequest(CloseNesRequest),
4941 #[cfg(feature = "unstable_mcp_over_acp")]
4947 MessageMcpRequest(MessageMcpRequest),
4948 ExtMethodRequest(ExtRequest),
4955}
4956
4957impl ClientRequest {
4958 #[must_use]
4960 pub fn method(&self) -> &str {
4961 match self {
4962 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
4963 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
4964 #[cfg(feature = "unstable_llm_providers")]
4965 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
4966 #[cfg(feature = "unstable_llm_providers")]
4967 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
4968 #[cfg(feature = "unstable_llm_providers")]
4969 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
4970 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
4971 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
4972 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
4973 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
4974 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
4975 #[cfg(feature = "unstable_session_fork")]
4976 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
4977 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
4978 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
4979 Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
4980 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
4981 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
4982 #[cfg(feature = "unstable_nes")]
4983 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
4984 #[cfg(feature = "unstable_nes")]
4985 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
4986 #[cfg(feature = "unstable_nes")]
4987 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
4988 #[cfg(feature = "unstable_mcp_over_acp")]
4989 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
4990 Self::ExtMethodRequest(ext_request) => &ext_request.method,
4991 }
4992 }
4993}
4994
4995#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5002#[derive(Clone, Debug, Serialize, Deserialize)]
5003#[serde(untagged)]
5004#[cfg_attr(feature = "schemars", schemars(inline))]
5005#[non_exhaustive]
5006#[allow(clippy::large_enum_variant)]
5007pub enum AgentResponse {
5008 InitializeResponse(InitializeResponse),
5010 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5012 #[cfg(feature = "unstable_llm_providers")]
5014 ListProvidersResponse(ListProvidersResponse),
5015 #[cfg(feature = "unstable_llm_providers")]
5017 SetProviderResponse(#[serde(default)] SetProviderResponse),
5018 #[cfg(feature = "unstable_llm_providers")]
5020 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5021 LogoutResponse(#[serde(default)] LogoutResponse),
5023 NewSessionResponse(NewSessionResponse),
5025 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5027 ListSessionsResponse(ListSessionsResponse),
5029 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5031 #[cfg(feature = "unstable_session_fork")]
5033 ForkSessionResponse(ForkSessionResponse),
5034 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5036 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5038 SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
5040 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5042 PromptResponse(PromptResponse),
5044 #[cfg(feature = "unstable_nes")]
5046 StartNesResponse(StartNesResponse),
5047 #[cfg(feature = "unstable_nes")]
5049 SuggestNesResponse(SuggestNesResponse),
5050 #[cfg(feature = "unstable_nes")]
5052 CloseNesResponse(#[serde(default)] CloseNesResponse),
5053 ExtMethodResponse(ExtResponse),
5055 #[cfg(feature = "unstable_mcp_over_acp")]
5057 MessageMcpResponse(MessageMcpResponse),
5058}
5059
5060#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5067#[derive(Clone, Debug, Serialize, Deserialize)]
5068#[serde(untagged)]
5069#[cfg_attr(feature = "schemars", schemars(inline))]
5070#[non_exhaustive]
5071#[allow(clippy::large_enum_variant)]
5072pub enum ClientNotification {
5073 CancelNotification(CancelNotification),
5085 #[cfg(feature = "unstable_nes")]
5086 DidOpenDocumentNotification(DidOpenDocumentNotification),
5090 #[cfg(feature = "unstable_nes")]
5091 DidChangeDocumentNotification(DidChangeDocumentNotification),
5095 #[cfg(feature = "unstable_nes")]
5096 DidCloseDocumentNotification(DidCloseDocumentNotification),
5100 #[cfg(feature = "unstable_nes")]
5101 DidSaveDocumentNotification(DidSaveDocumentNotification),
5105 #[cfg(feature = "unstable_nes")]
5106 DidFocusDocumentNotification(DidFocusDocumentNotification),
5110 #[cfg(feature = "unstable_nes")]
5111 AcceptNesNotification(AcceptNesNotification),
5115 #[cfg(feature = "unstable_nes")]
5116 RejectNesNotification(RejectNesNotification),
5120 #[cfg(feature = "unstable_mcp_over_acp")]
5126 MessageMcpNotification(MessageMcpNotification),
5127 ExtNotification(ExtNotification),
5134}
5135
5136impl ClientNotification {
5137 #[must_use]
5139 pub fn method(&self) -> &str {
5140 match self {
5141 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5142 #[cfg(feature = "unstable_nes")]
5143 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5144 #[cfg(feature = "unstable_nes")]
5145 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5146 #[cfg(feature = "unstable_nes")]
5147 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5148 #[cfg(feature = "unstable_nes")]
5149 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5150 #[cfg(feature = "unstable_nes")]
5151 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5152 #[cfg(feature = "unstable_nes")]
5153 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5154 #[cfg(feature = "unstable_nes")]
5155 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5156 #[cfg(feature = "unstable_mcp_over_acp")]
5157 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5158 Self::ExtNotification(ext_notification) => &ext_notification.method,
5159 }
5160 }
5161}
5162
5163#[serde_as]
5167#[skip_serializing_none]
5168#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
5169#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5170#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME)))]
5171#[serde(rename_all = "camelCase")]
5172#[non_exhaustive]
5173pub struct CancelNotification {
5174 pub session_id: SessionId,
5176 #[serde_as(deserialize_as = "DefaultOnError")]
5182 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
5183 #[serde(default)]
5184 #[serde(rename = "_meta")]
5185 pub meta: Option<Meta>,
5186}
5187
5188impl CancelNotification {
5189 #[must_use]
5191 pub fn new(session_id: impl Into<SessionId>) -> Self {
5192 Self {
5193 session_id: session_id.into(),
5194 meta: None,
5195 }
5196 }
5197
5198 #[must_use]
5204 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5205 self.meta = meta.into_option();
5206 self
5207 }
5208}
5209
5210#[cfg(test)]
5211mod test_serialization {
5212 use super::*;
5213 use serde_json::json;
5214
5215 fn test_meta() -> Meta {
5216 json!({ "source": "test" }).as_object().unwrap().clone()
5217 }
5218
5219 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5220 serde_json::to_string(value)
5221 .unwrap()
5222 .matches("\"_meta\"")
5223 .count()
5224 }
5225
5226 #[test]
5227 fn test_initialize_capabilities_default_on_malformed_values() {
5228 let request: InitializeRequest = serde_json::from_value(json!({
5229 "protocolVersion": 1,
5230 "clientCapabilities": false
5231 }))
5232 .unwrap();
5233 assert_eq!(request.client_capabilities, ClientCapabilities::default());
5234
5235 let response: InitializeResponse = serde_json::from_value(json!({
5236 "protocolVersion": 1,
5237 "agentCapabilities": false
5238 }))
5239 .unwrap();
5240 assert_eq!(response.agent_capabilities, AgentCapabilities::default());
5241 }
5242
5243 #[test]
5244 fn test_agent_capabilities_default_on_malformed_values() {
5245 let capabilities: AgentCapabilities = serde_json::from_value(json!({
5246 "loadSession": "yes",
5247 "promptCapabilities": {
5248 "image": "yes",
5249 "audio": true,
5250 "embeddedContext": {}
5251 },
5252 "mcpCapabilities": {
5253 "http": "yes",
5254 "sse": true
5255 },
5256 "sessionCapabilities": false,
5257 "auth": false
5258 }))
5259 .unwrap();
5260
5261 assert!(!capabilities.load_session);
5262 assert!(!capabilities.prompt_capabilities.image);
5263 assert!(capabilities.prompt_capabilities.audio);
5264 assert!(!capabilities.prompt_capabilities.embedded_context);
5265 assert!(!capabilities.mcp_capabilities.http);
5266 assert!(capabilities.mcp_capabilities.sse);
5267 assert_eq!(
5268 capabilities.session_capabilities,
5269 SessionCapabilities::default()
5270 );
5271 assert_eq!(capabilities.auth, AgentAuthCapabilities::default());
5272 }
5273
5274 #[test]
5275 fn test_mcp_server_stdio_serialization() {
5276 let server = McpServer::Stdio(
5277 McpServerStdio::new("test-server", "/usr/bin/server")
5278 .args(vec!["--port".to_string(), "3000".to_string()])
5279 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5280 );
5281
5282 let json = serde_json::to_value(&server).unwrap();
5283 assert_eq!(
5284 json,
5285 json!({
5286 "name": "test-server",
5287 "command": "/usr/bin/server",
5288 "args": ["--port", "3000"],
5289 "env": [
5290 {
5291 "name": "API_KEY",
5292 "value": "secret123"
5293 }
5294 ]
5295 })
5296 );
5297
5298 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5299 match deserialized {
5300 McpServer::Stdio(McpServerStdio {
5301 name,
5302 command,
5303 args,
5304 env,
5305 meta: _,
5306 }) => {
5307 assert_eq!(name, "test-server");
5308 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5309 assert_eq!(args, vec!["--port", "3000"]);
5310 assert_eq!(env.len(), 1);
5311 assert_eq!(env[0].name, "API_KEY");
5312 assert_eq!(env[0].value, "secret123");
5313 }
5314 _ => panic!("Expected Stdio variant"),
5315 }
5316 }
5317
5318 #[test]
5319 fn test_mcp_server_http_serialization() {
5320 let server = McpServer::Http(
5321 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5322 HttpHeader::new("Authorization", "Bearer token123"),
5323 HttpHeader::new("Content-Type", "application/json"),
5324 ]),
5325 );
5326
5327 let json = serde_json::to_value(&server).unwrap();
5328 assert_eq!(
5329 json,
5330 json!({
5331 "type": "http",
5332 "name": "http-server",
5333 "url": "https://api.example.com",
5334 "headers": [
5335 {
5336 "name": "Authorization",
5337 "value": "Bearer token123"
5338 },
5339 {
5340 "name": "Content-Type",
5341 "value": "application/json"
5342 }
5343 ]
5344 })
5345 );
5346
5347 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5348 match deserialized {
5349 McpServer::Http(McpServerHttp {
5350 name,
5351 url,
5352 headers,
5353 meta: _,
5354 }) => {
5355 assert_eq!(name, "http-server");
5356 assert_eq!(url, "https://api.example.com");
5357 assert_eq!(headers.len(), 2);
5358 assert_eq!(headers[0].name, "Authorization");
5359 assert_eq!(headers[0].value, "Bearer token123");
5360 assert_eq!(headers[1].name, "Content-Type");
5361 assert_eq!(headers[1].value, "application/json");
5362 }
5363 _ => panic!("Expected Http variant"),
5364 }
5365 }
5366
5367 #[cfg(feature = "unstable_mcp_over_acp")]
5368 #[test]
5369 fn test_mcp_server_acp_serialization() {
5370 let server = McpServer::Acp(McpServerAcp::new("project-tools", "project-tools-id"));
5371
5372 let json = serde_json::to_value(&server).unwrap();
5373 assert_eq!(
5374 json,
5375 json!({
5376 "type": "acp",
5377 "name": "project-tools",
5378 "serverId": "project-tools-id"
5379 })
5380 );
5381
5382 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5383 match deserialized {
5384 McpServer::Acp(McpServerAcp {
5385 name,
5386 server_id: id,
5387 meta: _,
5388 }) => {
5389 assert_eq!(name, "project-tools");
5390 assert_eq!(id, McpServerAcpId::new("project-tools-id"));
5391 }
5392 _ => panic!("Expected Acp variant"),
5393 }
5394 }
5395
5396 #[cfg(feature = "unstable_mcp_over_acp")]
5397 #[test]
5398 fn test_client_mcp_message_method_names() {
5399 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5400
5401 assert_eq!(
5402 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5403 .method(),
5404 "mcp/message"
5405 );
5406 assert_eq!(
5407 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5408 "conn-1",
5409 "notifications/progress"
5410 ))
5411 .method(),
5412 "mcp/message"
5413 );
5414 }
5415
5416 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5417 #[test]
5418 fn test_mcp_server_acp_schema() {
5419 let mcp_server_schema = serde_json::to_value(schemars::schema_for!(McpServer)).unwrap();
5420 assert!(json_contains_entry(
5421 &mcp_server_schema,
5422 "const",
5423 &json!("acp")
5424 ));
5425 assert!(json_contains_entry(
5426 &mcp_server_schema,
5427 "$ref",
5428 &json!("#/$defs/McpServerAcp")
5429 ));
5430
5431 let capabilities_schema =
5432 serde_json::to_value(schemars::schema_for!(McpCapabilities)).unwrap();
5433 assert!(json_contains_key(&capabilities_schema, "acp"));
5434 }
5435
5436 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5437 fn json_contains_entry(
5438 value: &serde_json::Value,
5439 key: &str,
5440 expected: &serde_json::Value,
5441 ) -> bool {
5442 match value {
5443 serde_json::Value::Object(map) => {
5444 map.get(key) == Some(expected)
5445 || map
5446 .values()
5447 .any(|value| json_contains_entry(value, key, expected))
5448 }
5449 serde_json::Value::Array(values) => values
5450 .iter()
5451 .any(|value| json_contains_entry(value, key, expected)),
5452 _ => false,
5453 }
5454 }
5455
5456 #[cfg(all(feature = "unstable_mcp_over_acp", feature = "schemars"))]
5457 fn json_contains_key(value: &serde_json::Value, key: &str) -> bool {
5458 match value {
5459 serde_json::Value::Object(map) => {
5460 map.contains_key(key) || map.values().any(|value| json_contains_key(value, key))
5461 }
5462 serde_json::Value::Array(values) => {
5463 values.iter().any(|value| json_contains_key(value, key))
5464 }
5465 _ => false,
5466 }
5467 }
5468
5469 #[test]
5470 fn test_mcp_server_sse_serialization() {
5471 let server = McpServer::Sse(
5472 McpServerSse::new("sse-server", "https://sse.example.com/events")
5473 .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
5474 );
5475
5476 let json = serde_json::to_value(&server).unwrap();
5477 assert_eq!(
5478 json,
5479 json!({
5480 "type": "sse",
5481 "name": "sse-server",
5482 "url": "https://sse.example.com/events",
5483 "headers": [
5484 {
5485 "name": "X-API-Key",
5486 "value": "apikey456"
5487 }
5488 ]
5489 })
5490 );
5491
5492 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5493 match deserialized {
5494 McpServer::Sse(McpServerSse {
5495 name,
5496 url,
5497 headers,
5498 meta: _,
5499 }) => {
5500 assert_eq!(name, "sse-server");
5501 assert_eq!(url, "https://sse.example.com/events");
5502 assert_eq!(headers.len(), 1);
5503 assert_eq!(headers[0].name, "X-API-Key");
5504 assert_eq!(headers[0].value, "apikey456");
5505 }
5506 _ => panic!("Expected Sse variant"),
5507 }
5508 }
5509
5510 #[test]
5511 fn test_session_config_option_category_known_variants() {
5512 assert_eq!(
5514 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5515 json!("mode")
5516 );
5517 assert_eq!(
5518 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5519 json!("model")
5520 );
5521 assert_eq!(
5522 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5523 json!("model_config")
5524 );
5525 assert_eq!(
5526 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5527 json!("thought_level")
5528 );
5529
5530 assert_eq!(
5532 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5533 SessionConfigOptionCategory::Mode
5534 );
5535 assert_eq!(
5536 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5537 SessionConfigOptionCategory::Model
5538 );
5539 assert_eq!(
5540 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5541 SessionConfigOptionCategory::ModelConfig
5542 );
5543 assert_eq!(
5544 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5545 SessionConfigOptionCategory::ThoughtLevel
5546 );
5547 }
5548
5549 #[test]
5550 fn test_session_config_option_category_unknown_variants() {
5551 let unknown: SessionConfigOptionCategory =
5553 serde_json::from_str("\"some_future_category\"").unwrap();
5554 assert_eq!(
5555 unknown,
5556 SessionConfigOptionCategory::Other("some_future_category".to_string())
5557 );
5558
5559 let json = serde_json::to_value(&unknown).unwrap();
5561 assert_eq!(json, json!("some_future_category"));
5562 }
5563
5564 #[test]
5565 fn test_session_config_option_category_custom_categories() {
5566 let custom: SessionConfigOptionCategory =
5568 serde_json::from_str("\"_my_custom_category\"").unwrap();
5569 assert_eq!(
5570 custom,
5571 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5572 );
5573
5574 let json = serde_json::to_value(&custom).unwrap();
5576 assert_eq!(json, json!("_my_custom_category"));
5577
5578 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5580 assert_eq!(
5581 deserialized,
5582 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5583 );
5584 }
5585
5586 #[test]
5587 fn test_auth_method_agent_serialization() {
5588 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5589
5590 let json = serde_json::to_value(&method).unwrap();
5591 assert_eq!(
5592 json,
5593 json!({
5594 "id": "default-auth",
5595 "name": "Default Auth"
5596 })
5597 );
5598 assert!(!json.as_object().unwrap().contains_key("description"));
5600 assert!(!json.as_object().unwrap().contains_key("type"));
5602
5603 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5604 match deserialized {
5605 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5606 assert_eq!(id.0.as_ref(), "default-auth");
5607 assert_eq!(name, "Default Auth");
5608 }
5609 _ => panic!("Expected Agent variant"),
5610 }
5611 }
5612
5613 #[test]
5614 fn test_auth_method_explicit_agent_deserialization() {
5615 let json = json!({
5617 "id": "agent-auth",
5618 "name": "Agent Auth",
5619 "type": "agent"
5620 });
5621
5622 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5623 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5624 }
5625
5626 #[test]
5627 fn test_session_delete_serialization() {
5628 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5629 assert_eq!(
5630 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5631 "session/delete"
5632 );
5633 assert_eq!(
5634 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5635 json!({
5636 "sessionId": "sess_abc123"
5637 })
5638 );
5639 assert_eq!(
5640 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5641 json!({})
5642 );
5643 assert_eq!(
5644 serde_json::to_value(
5645 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5646 )
5647 .unwrap(),
5648 json!({
5649 "delete": {}
5650 })
5651 );
5652 }
5653 #[test]
5654 fn test_session_additional_directories_serialization() {
5655 assert_eq!(
5656 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5657 json!({
5658 "cwd": "/home/user/project",
5659 "mcpServers": []
5660 })
5661 );
5662 assert_eq!(
5663 serde_json::to_value(
5664 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5665 PathBuf::from("/home/user/shared-lib"),
5666 PathBuf::from("/home/user/product-docs"),
5667 ])
5668 )
5669 .unwrap(),
5670 json!({
5671 "cwd": "/home/user/project",
5672 "additionalDirectories": [
5673 "/home/user/shared-lib",
5674 "/home/user/product-docs"
5675 ],
5676 "mcpServers": []
5677 })
5678 );
5679 assert_eq!(
5680 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5681 json!({
5682 "sessionId": "sess_abc123",
5683 "cwd": "/home/user/project"
5684 })
5685 );
5686 assert_eq!(
5687 serde_json::to_value(
5688 SessionInfo::new("sess_abc123", "/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 "sessionId": "sess_abc123",
5696 "cwd": "/home/user/project",
5697 "additionalDirectories": [
5698 "/home/user/shared-lib",
5699 "/home/user/product-docs"
5700 ]
5701 })
5702 );
5703 assert_eq!(
5704 serde_json::from_value::<SessionInfo>(json!({
5705 "sessionId": "sess_abc123",
5706 "cwd": "/home/user/project"
5707 }))
5708 .unwrap()
5709 .additional_directories,
5710 Vec::<PathBuf>::new()
5711 );
5712 }
5713 #[test]
5714 fn test_session_additional_directories_capabilities_serialization() {
5715 assert_eq!(
5716 serde_json::to_value(
5717 SessionCapabilities::new()
5718 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5719 )
5720 .unwrap(),
5721 json!({
5722 "additionalDirectories": {}
5723 })
5724 );
5725 }
5726
5727 #[test]
5728 fn test_auth_method_terminal_serialization() {
5729 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5730
5731 let json = serde_json::to_value(&method).unwrap();
5732 assert_eq!(
5733 json,
5734 json!({
5735 "id": "tui-auth",
5736 "name": "Terminal Auth",
5737 "type": "terminal"
5738 })
5739 );
5740 assert!(!json.as_object().unwrap().contains_key("args"));
5742 assert!(!json.as_object().unwrap().contains_key("env"));
5743
5744 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5745 match deserialized {
5746 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5747 assert!(args.is_empty());
5748 assert!(env.is_empty());
5749 }
5750 _ => panic!("Expected Terminal variant"),
5751 }
5752 }
5753
5754 #[test]
5755 fn test_auth_method_terminal_with_args_and_env_serialization() {
5756 use std::collections::HashMap;
5757
5758 let mut env = HashMap::new();
5759 env.insert("TERM".to_string(), "xterm-256color".to_string());
5760
5761 let method = AuthMethod::Terminal(
5762 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5763 .args(vec!["--interactive".to_string(), "--color".to_string()])
5764 .env(env),
5765 );
5766
5767 let json = serde_json::to_value(&method).unwrap();
5768 assert_eq!(
5769 json,
5770 json!({
5771 "id": "tui-auth",
5772 "name": "Terminal Auth",
5773 "type": "terminal",
5774 "args": ["--interactive", "--color"],
5775 "env": {
5776 "TERM": "xterm-256color"
5777 }
5778 })
5779 );
5780
5781 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5782 match deserialized {
5783 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5784 assert_eq!(args, vec!["--interactive", "--color"]);
5785 assert_eq!(env.len(), 1);
5786 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
5787 }
5788 _ => panic!("Expected Terminal variant"),
5789 }
5790 }
5791
5792 #[test]
5793 fn test_session_config_option_value_id_serialize() {
5794 let val = SessionConfigOptionValue::value_id("model-1");
5795 let json = serde_json::to_value(&val).unwrap();
5796 assert_eq!(json, json!({ "value": "model-1" }));
5798 assert!(!json.as_object().unwrap().contains_key("type"));
5799 }
5800
5801 #[test]
5802 fn test_session_config_option_value_boolean_serialize() {
5803 let val = SessionConfigOptionValue::boolean(true);
5804 let json = serde_json::to_value(&val).unwrap();
5805 assert_eq!(json, json!({ "type": "boolean", "value": true }));
5806 }
5807
5808 #[test]
5809 fn test_session_config_option_value_deserialize_no_type() {
5810 let json = json!({ "value": "model-1" });
5812 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5813 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
5814 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
5815 }
5816
5817 #[test]
5818 fn test_session_config_option_value_deserialize_boolean() {
5819 let json = json!({ "type": "boolean", "value": true });
5820 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5821 assert_eq!(val, SessionConfigOptionValue::boolean(true));
5822 assert_eq!(val.as_bool(), Some(true));
5823 }
5824
5825 #[test]
5826 fn test_session_config_option_value_deserialize_boolean_false() {
5827 let json = json!({ "type": "boolean", "value": false });
5828 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5829 assert_eq!(val, SessionConfigOptionValue::boolean(false));
5830 assert_eq!(val.as_bool(), Some(false));
5831 }
5832
5833 #[test]
5834 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
5835 let json = json!({ "type": "text", "value": "freeform input" });
5837 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5838 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
5839 }
5840
5841 #[test]
5842 fn test_session_config_option_value_roundtrip_value_id() {
5843 let original = SessionConfigOptionValue::value_id("option-a");
5844 let json = serde_json::to_value(&original).unwrap();
5845 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5846 assert_eq!(original, roundtripped);
5847 }
5848
5849 #[test]
5850 fn test_session_config_option_value_roundtrip_boolean() {
5851 let original = SessionConfigOptionValue::boolean(false);
5852 let json = serde_json::to_value(&original).unwrap();
5853 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
5854 assert_eq!(original, roundtripped);
5855 }
5856
5857 #[test]
5858 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
5859 let json = json!({ "type": "boolean", "value": "not a bool" });
5861 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
5862 assert!(result.is_ok());
5864 assert_eq!(
5865 result.unwrap().as_value_id().unwrap().to_string(),
5866 "not a bool"
5867 );
5868 }
5869
5870 #[test]
5871 fn test_session_config_option_value_from_impls() {
5872 let from_str: SessionConfigOptionValue = "model-1".into();
5873 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
5874
5875 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
5876 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
5877
5878 let from_bool: SessionConfigOptionValue = true.into();
5879 assert_eq!(from_bool.as_bool(), Some(true));
5880 }
5881
5882 #[test]
5883 fn test_set_session_config_option_request_value_id() {
5884 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
5885 let json = serde_json::to_value(&req).unwrap();
5886 assert_eq!(
5887 json,
5888 json!({
5889 "sessionId": "sess_1",
5890 "configId": "model",
5891 "value": "model-1"
5892 })
5893 );
5894 assert!(!json.as_object().unwrap().contains_key("type"));
5896 }
5897
5898 #[test]
5899 fn test_set_session_config_option_request_boolean() {
5900 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
5901 let json = serde_json::to_value(&req).unwrap();
5902 assert_eq!(
5903 json,
5904 json!({
5905 "sessionId": "sess_1",
5906 "configId": "brave_mode",
5907 "type": "boolean",
5908 "value": true
5909 })
5910 );
5911 }
5912
5913 #[test]
5914 fn test_set_session_config_option_request_deserialize_no_type() {
5915 let json = json!({
5917 "sessionId": "sess_1",
5918 "configId": "model",
5919 "value": "model-1"
5920 });
5921 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5922 assert_eq!(req.session_id.to_string(), "sess_1");
5923 assert_eq!(req.config_id.to_string(), "model");
5924 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
5925 }
5926
5927 #[test]
5928 fn test_set_session_config_option_request_deserialize_boolean() {
5929 let json = json!({
5930 "sessionId": "sess_1",
5931 "configId": "brave_mode",
5932 "type": "boolean",
5933 "value": true
5934 });
5935 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5936 assert_eq!(req.value.as_bool(), Some(true));
5937 }
5938
5939 #[test]
5940 fn test_set_session_config_option_request_roundtrip_value_id() {
5941 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
5942 let json = serde_json::to_value(&original).unwrap();
5943 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5944 assert_eq!(original, roundtripped);
5945 }
5946
5947 #[test]
5948 fn test_set_session_config_option_request_roundtrip_boolean() {
5949 let original = SetSessionConfigOptionRequest::new("s", "c", false);
5950 let json = serde_json::to_value(&original).unwrap();
5951 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
5952 assert_eq!(original, roundtripped);
5953 }
5954
5955 #[test]
5956 fn test_session_config_boolean_serialization() {
5957 let cfg = SessionConfigBoolean::new(true);
5958 let json = serde_json::to_value(&cfg).unwrap();
5959 assert_eq!(json, json!({ "currentValue": true }));
5960
5961 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
5962 assert!(deserialized.current_value);
5963 }
5964
5965 #[test]
5966 fn test_session_config_option_boolean_variant() {
5967 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
5968 .description("Skip confirmation prompts")
5969 .meta(test_meta());
5970 assert_eq!(serialized_meta_key_count(&opt), 1);
5971
5972 let json = serde_json::to_value(&opt).unwrap();
5973 assert_eq!(
5974 json,
5975 json!({
5976 "id": "brave_mode",
5977 "name": "Brave Mode",
5978 "description": "Skip confirmation prompts",
5979 "type": "boolean",
5980 "currentValue": false,
5981 "_meta": {
5982 "source": "test"
5983 }
5984 })
5985 );
5986
5987 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
5988 assert_eq!(deserialized.id.to_string(), "brave_mode");
5989 assert_eq!(deserialized.name, "Brave Mode");
5990 match deserialized.kind {
5991 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
5992 _ => panic!("Expected Boolean kind"),
5993 }
5994 }
5995
5996 #[test]
5997 fn test_session_config_option_select_still_works() {
5998 let opt = SessionConfigOption::select(
6000 "model",
6001 "Model",
6002 "model-1",
6003 vec![
6004 SessionConfigSelectOption::new("model-1", "Model 1"),
6005 SessionConfigSelectOption::new("model-2", "Model 2"),
6006 ],
6007 )
6008 .meta(test_meta());
6009 assert_eq!(serialized_meta_key_count(&opt), 1);
6010
6011 let json = serde_json::to_value(&opt).unwrap();
6012 assert_eq!(json["type"], "select");
6013 assert_eq!(json["currentValue"], "model-1");
6014 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6015 assert_eq!(json["_meta"]["source"], "test");
6016
6017 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6018 match deserialized.kind {
6019 SessionConfigKind::Select(ref s) => {
6020 assert_eq!(s.current_value.to_string(), "model-1");
6021 }
6022 _ => panic!("Expected Select kind"),
6023 }
6024 }
6025
6026 #[cfg(feature = "unstable_llm_providers")]
6027 #[test]
6028 fn test_llm_protocol_known_variants() {
6029 assert_eq!(
6030 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6031 json!("anthropic")
6032 );
6033 assert_eq!(
6034 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6035 json!("openai")
6036 );
6037 assert_eq!(
6038 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6039 json!("azure")
6040 );
6041 assert_eq!(
6042 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6043 json!("vertex")
6044 );
6045 assert_eq!(
6046 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6047 json!("bedrock")
6048 );
6049
6050 assert_eq!(
6051 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6052 LlmProtocol::Anthropic
6053 );
6054 assert_eq!(
6055 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6056 LlmProtocol::OpenAi
6057 );
6058 assert_eq!(
6059 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6060 LlmProtocol::Azure
6061 );
6062 assert_eq!(
6063 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6064 LlmProtocol::Vertex
6065 );
6066 assert_eq!(
6067 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6068 LlmProtocol::Bedrock
6069 );
6070 }
6071
6072 #[cfg(feature = "unstable_llm_providers")]
6073 #[test]
6074 fn test_llm_protocol_unknown_variant() {
6075 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6076 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6077
6078 let json = serde_json::to_value(&unknown).unwrap();
6079 assert_eq!(json, json!("cohere"));
6080 }
6081
6082 #[cfg(feature = "unstable_llm_providers")]
6083 #[test]
6084 fn test_provider_current_config_serialization() {
6085 let config =
6086 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6087
6088 let json = serde_json::to_value(&config).unwrap();
6089 assert_eq!(
6090 json,
6091 json!({
6092 "apiType": "anthropic",
6093 "baseUrl": "https://api.anthropic.com"
6094 })
6095 );
6096
6097 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6098 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6099 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6100 }
6101
6102 #[cfg(feature = "unstable_llm_providers")]
6103 #[test]
6104 fn test_provider_info_with_current_config() {
6105 let info = ProviderInfo::new(
6106 "main",
6107 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6108 true,
6109 Some(ProviderCurrentConfig::new(
6110 LlmProtocol::Anthropic,
6111 "https://api.anthropic.com",
6112 )),
6113 );
6114
6115 let json = serde_json::to_value(&info).unwrap();
6116 assert_eq!(
6117 json,
6118 json!({
6119 "providerId": "main",
6120 "supported": ["anthropic", "openai"],
6121 "required": true,
6122 "current": {
6123 "apiType": "anthropic",
6124 "baseUrl": "https://api.anthropic.com"
6125 }
6126 })
6127 );
6128
6129 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6130 assert_eq!(deserialized.provider_id.to_string(), "main");
6131 assert_eq!(deserialized.supported.len(), 2);
6132 assert!(deserialized.required);
6133 assert!(deserialized.current.is_some());
6134 assert_eq!(
6135 deserialized.current.as_ref().unwrap().api_type,
6136 LlmProtocol::Anthropic
6137 );
6138 }
6139
6140 #[cfg(feature = "unstable_llm_providers")]
6141 #[test]
6142 fn test_provider_info_disabled() {
6143 let info = ProviderInfo::new(
6144 "secondary",
6145 vec![LlmProtocol::OpenAi],
6146 false,
6147 None::<ProviderCurrentConfig>,
6148 );
6149
6150 let json = serde_json::to_value(&info).unwrap();
6151 assert_eq!(
6152 json,
6153 json!({
6154 "providerId": "secondary",
6155 "supported": ["openai"],
6156 "required": false
6157 })
6158 );
6159
6160 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6161 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6162 assert!(!deserialized.required);
6163 assert!(deserialized.current.is_none());
6164 }
6165
6166 #[cfg(feature = "unstable_llm_providers")]
6167 #[test]
6168 fn test_provider_info_missing_current_defaults_to_none() {
6169 let json = json!({
6171 "providerId": "main",
6172 "supported": ["anthropic"],
6173 "required": true
6174 });
6175 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6176 assert!(deserialized.current.is_none());
6177 }
6178
6179 #[cfg(feature = "unstable_llm_providers")]
6180 #[test]
6181 fn test_provider_info_explicit_null_current_decodes_to_none() {
6182 let json = json!({
6186 "providerId": "main",
6187 "supported": ["anthropic"],
6188 "required": true,
6189 "current": null
6190 });
6191 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6192 assert!(deserialized.current.is_none());
6193 }
6194
6195 #[cfg(feature = "unstable_llm_providers")]
6196 #[test]
6197 fn test_list_providers_response_serialization() {
6198 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6199 "main",
6200 vec![LlmProtocol::Anthropic],
6201 true,
6202 Some(ProviderCurrentConfig::new(
6203 LlmProtocol::Anthropic,
6204 "https://api.anthropic.com",
6205 )),
6206 )]);
6207
6208 let json = serde_json::to_value(&response).unwrap();
6209 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6210 assert_eq!(json["providers"][0]["providerId"], "main");
6211
6212 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6213 assert_eq!(deserialized.providers.len(), 1);
6214 }
6215
6216 #[cfg(feature = "unstable_llm_providers")]
6217 #[test]
6218 fn test_set_provider_request_serialization() {
6219 use std::collections::HashMap;
6220
6221 let mut headers = HashMap::new();
6222 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6223
6224 let request =
6225 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6226 .headers(headers);
6227
6228 let json = serde_json::to_value(&request).unwrap();
6229 assert_eq!(
6230 json,
6231 json!({
6232 "providerId": "main",
6233 "apiType": "openai",
6234 "baseUrl": "https://api.openai.com/v1",
6235 "headers": {
6236 "Authorization": "Bearer sk-test"
6237 }
6238 })
6239 );
6240
6241 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6242 assert_eq!(deserialized.provider_id.to_string(), "main");
6243 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6244 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6245 assert_eq!(deserialized.headers.len(), 1);
6246 assert_eq!(
6247 deserialized.headers.get("Authorization").unwrap(),
6248 "Bearer sk-test"
6249 );
6250 }
6251
6252 #[cfg(feature = "unstable_llm_providers")]
6253 #[test]
6254 fn test_set_provider_request_omits_empty_headers() {
6255 let request =
6256 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6257
6258 let json = serde_json::to_value(&request).unwrap();
6259 assert!(!json.as_object().unwrap().contains_key("headers"));
6261 }
6262
6263 #[cfg(feature = "unstable_llm_providers")]
6264 #[test]
6265 fn test_disable_provider_request_serialization() {
6266 let request = DisableProviderRequest::new("secondary");
6267
6268 let json = serde_json::to_value(&request).unwrap();
6269 assert_eq!(json, json!({ "providerId": "secondary" }));
6270
6271 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6272 assert_eq!(deserialized.provider_id.to_string(), "secondary");
6273 }
6274
6275 #[cfg(feature = "unstable_llm_providers")]
6276 #[test]
6277 fn test_providers_capabilities_serialization() {
6278 let caps = ProvidersCapabilities::new();
6279
6280 let json = serde_json::to_value(&caps).unwrap();
6281 assert_eq!(json, json!({}));
6282
6283 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6284 assert!(deserialized.meta.is_none());
6285 }
6286
6287 #[cfg(feature = "unstable_llm_providers")]
6288 #[test]
6289 fn test_agent_capabilities_with_providers() {
6290 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6291
6292 let json = serde_json::to_value(&caps).unwrap();
6293 assert_eq!(json["providers"], json!({}));
6294
6295 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6296 assert!(deserialized.providers.is_some());
6297 }
6298
6299 #[test]
6300 fn prompt_request_rejects_malformed_content_block() {
6301 use serde_json::json;
6302
6303 assert!(
6304 serde_json::from_value::<PromptRequest>(json!({
6305 "sessionId": "sess-1",
6306 "prompt": [{"type": "text"}]
6307 }))
6308 .is_err()
6309 );
6310 }
6311
6312 #[test]
6313 fn prompt_request_rejects_non_array_prompt() {
6314 use serde_json::json;
6315
6316 assert!(
6317 serde_json::from_value::<PromptRequest>(json!({
6318 "sessionId": "sess-1",
6319 "prompt": "hello"
6320 }))
6321 .is_err()
6322 );
6323 }
6324}