1use std::{path::PathBuf, sync::Arc};
7
8use derive_more::{Display, From};
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11use serde_json::value::RawValue;
12
13use crate::{
14 ContentBlock, ExtNotification, Plan, SessionId, SessionModeId, ToolCall, ToolCallUpdate,
15 ext::ExtRequest,
16};
17
18#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
26#[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))]
27#[serde(rename_all = "camelCase")]
28#[non_exhaustive]
29pub struct SessionNotification {
30 pub session_id: SessionId,
32 pub update: SessionUpdate,
34 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
36 pub meta: Option<serde_json::Value>,
37}
38
39impl SessionNotification {
40 #[must_use]
41 pub fn new(session_id: SessionId, update: SessionUpdate) -> Self {
42 Self {
43 session_id,
44 update,
45 meta: None,
46 }
47 }
48
49 #[must_use]
51 pub fn meta(mut self, meta: serde_json::Value) -> Self {
52 self.meta = Some(meta);
53 self
54 }
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
63#[serde(tag = "sessionUpdate", rename_all = "snake_case")]
64#[schemars(extend("discriminator" = {"propertyName": "sessionUpdate"}))]
65#[non_exhaustive]
66pub enum SessionUpdate {
67 UserMessageChunk(ContentChunk),
69 AgentMessageChunk(ContentChunk),
71 AgentThoughtChunk(ContentChunk),
73 ToolCall(ToolCall),
75 ToolCallUpdate(ToolCallUpdate),
77 Plan(Plan),
80 AvailableCommandsUpdate(AvailableCommandsUpdate),
82 CurrentModeUpdate(CurrentModeUpdate),
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
92#[serde(rename_all = "camelCase")]
93#[non_exhaustive]
94pub struct CurrentModeUpdate {
95 pub current_mode_id: SessionModeId,
97 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
99 pub meta: Option<serde_json::Value>,
100}
101
102impl CurrentModeUpdate {
103 #[must_use]
104 pub fn new(current_mode_id: SessionModeId) -> Self {
105 Self {
106 current_mode_id,
107 meta: None,
108 }
109 }
110
111 #[must_use]
113 pub fn meta(mut self, meta: serde_json::Value) -> Self {
114 self.meta = Some(meta);
115 self
116 }
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
121#[serde(rename_all = "camelCase")]
122#[non_exhaustive]
123pub struct ContentChunk {
124 pub content: ContentBlock,
126 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
128 pub meta: Option<serde_json::Value>,
129}
130
131impl ContentChunk {
132 #[must_use]
133 pub fn new(content: ContentBlock) -> Self {
134 Self {
135 content,
136 meta: None,
137 }
138 }
139
140 #[must_use]
142 pub fn meta(mut self, meta: serde_json::Value) -> Self {
143 self.meta = Some(meta);
144 self
145 }
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
150#[serde(rename_all = "camelCase")]
151#[non_exhaustive]
152pub struct AvailableCommandsUpdate {
153 pub available_commands: Vec<AvailableCommand>,
155 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
157 pub meta: Option<serde_json::Value>,
158}
159
160impl AvailableCommandsUpdate {
161 #[must_use]
162 pub fn new(available_commands: Vec<AvailableCommand>) -> Self {
163 Self {
164 available_commands,
165 meta: None,
166 }
167 }
168
169 #[must_use]
171 pub fn meta(mut self, meta: serde_json::Value) -> Self {
172 self.meta = Some(meta);
173 self
174 }
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
179#[serde(rename_all = "camelCase")]
180#[non_exhaustive]
181pub struct AvailableCommand {
182 pub name: String,
184 pub description: String,
186 pub input: Option<AvailableCommandInput>,
188 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
190 pub meta: Option<serde_json::Value>,
191}
192
193impl AvailableCommand {
194 pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
195 Self {
196 name: name.into(),
197 description: description.into(),
198 input: None,
199 meta: None,
200 }
201 }
202
203 #[must_use]
205 pub fn input(mut self, input: AvailableCommandInput) -> Self {
206 self.input = Some(input);
207 self
208 }
209
210 #[must_use]
212 pub fn meta(mut self, meta: serde_json::Value) -> Self {
213 self.meta = Some(meta);
214 self
215 }
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
220#[serde(untagged, rename_all = "camelCase")]
221#[non_exhaustive]
222pub enum AvailableCommandInput {
223 Unstructured(UnstructuredCommandInput),
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
229#[serde(rename_all = "camelCase")]
230#[non_exhaustive]
231pub struct UnstructuredCommandInput {
232 pub hint: String,
234 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
236 pub meta: Option<serde_json::Value>,
237}
238
239impl UnstructuredCommandInput {
240 pub fn new(hint: impl Into<String>) -> Self {
241 Self {
242 hint: hint.into(),
243 meta: None,
244 }
245 }
246
247 #[must_use]
249 pub fn meta(mut self, meta: serde_json::Value) -> Self {
250 self.meta = Some(meta);
251 self
252 }
253}
254
255#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
263#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
264#[serde(rename_all = "camelCase")]
265#[non_exhaustive]
266pub struct RequestPermissionRequest {
267 pub session_id: SessionId,
269 pub tool_call: ToolCallUpdate,
271 pub options: Vec<PermissionOption>,
273 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
275 pub meta: Option<serde_json::Value>,
276}
277
278impl RequestPermissionRequest {
279 #[must_use]
280 pub fn new(
281 session_id: SessionId,
282 tool_call: ToolCallUpdate,
283 options: Vec<PermissionOption>,
284 ) -> Self {
285 Self {
286 session_id,
287 tool_call,
288 options,
289 meta: None,
290 }
291 }
292
293 #[must_use]
295 pub fn meta(mut self, meta: serde_json::Value) -> Self {
296 self.meta = Some(meta);
297 self
298 }
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
303#[serde(rename_all = "camelCase")]
304#[non_exhaustive]
305pub struct PermissionOption {
306 pub option_id: PermissionOptionId,
308 pub name: String,
310 pub kind: PermissionOptionKind,
312 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
314 pub meta: Option<serde_json::Value>,
315}
316
317impl PermissionOption {
318 pub fn new(
319 option_id: PermissionOptionId,
320 name: impl Into<String>,
321 kind: PermissionOptionKind,
322 ) -> Self {
323 Self {
324 option_id,
325 name: name.into(),
326 kind,
327 meta: None,
328 }
329 }
330
331 #[must_use]
333 pub fn meta(mut self, meta: serde_json::Value) -> Self {
334 self.meta = Some(meta);
335 self
336 }
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
341#[serde(transparent)]
342#[from(Arc<str>, String, &'static str)]
343#[non_exhaustive]
344pub struct PermissionOptionId(pub Arc<str>);
345
346impl PermissionOptionId {
347 pub fn new(id: impl Into<Arc<str>>) -> Self {
348 Self(id.into())
349 }
350}
351
352#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
356#[serde(rename_all = "snake_case")]
357#[non_exhaustive]
358pub enum PermissionOptionKind {
359 AllowOnce,
361 AllowAlways,
363 RejectOnce,
365 RejectAlways,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
371#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
372#[serde(rename_all = "camelCase")]
373#[non_exhaustive]
374pub struct RequestPermissionResponse {
375 pub outcome: RequestPermissionOutcome,
378 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
380 pub meta: Option<serde_json::Value>,
381}
382
383impl RequestPermissionResponse {
384 #[must_use]
385 pub fn new(outcome: RequestPermissionOutcome) -> Self {
386 Self {
387 outcome,
388 meta: None,
389 }
390 }
391
392 #[must_use]
394 pub fn meta(mut self, meta: serde_json::Value) -> Self {
395 self.meta = Some(meta);
396 self
397 }
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
402#[serde(tag = "outcome", rename_all = "snake_case")]
403#[schemars(extend("discriminator" = {"propertyName": "outcome"}))]
404#[non_exhaustive]
405pub enum RequestPermissionOutcome {
406 Cancelled,
414 #[serde(rename_all = "camelCase")]
416 Selected(SelectedPermissionOutcome),
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
421#[serde(rename_all = "camelCase")]
422#[non_exhaustive]
423pub struct SelectedPermissionOutcome {
424 pub option_id: PermissionOptionId,
426 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
428 pub meta: Option<serde_json::Value>,
429}
430
431impl SelectedPermissionOutcome {
432 #[must_use]
433 pub fn new(option_id: PermissionOptionId) -> Self {
434 Self {
435 option_id,
436 meta: None,
437 }
438 }
439
440 #[must_use]
442 pub fn meta(mut self, meta: serde_json::Value) -> Self {
443 self.meta = Some(meta);
444 self
445 }
446}
447
448#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
454#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
455#[serde(rename_all = "camelCase")]
456#[non_exhaustive]
457pub struct WriteTextFileRequest {
458 pub session_id: SessionId,
460 pub path: PathBuf,
462 pub content: String,
464 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
466 pub meta: Option<serde_json::Value>,
467}
468
469impl WriteTextFileRequest {
470 pub fn new(
471 session_id: SessionId,
472 path: impl Into<PathBuf>,
473 content: impl Into<String>,
474 ) -> Self {
475 Self {
476 session_id,
477 path: path.into(),
478 content: content.into(),
479 meta: None,
480 }
481 }
482
483 #[must_use]
485 pub fn meta(mut self, meta: serde_json::Value) -> Self {
486 self.meta = Some(meta);
487 self
488 }
489}
490
491#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
493#[serde(default, rename_all = "camelCase")]
494#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
495#[non_exhaustive]
496pub struct WriteTextFileResponse {
497 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
499 pub meta: Option<serde_json::Value>,
500}
501
502impl WriteTextFileResponse {
503 #[must_use]
504 pub fn new() -> Self {
505 Self::default()
506 }
507
508 #[must_use]
510 pub fn meta(mut self, meta: serde_json::Value) -> Self {
511 self.meta = Some(meta);
512 self
513 }
514}
515
516#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
522#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
523#[serde(rename_all = "camelCase")]
524#[non_exhaustive]
525pub struct ReadTextFileRequest {
526 pub session_id: SessionId,
528 pub path: PathBuf,
530 #[serde(skip_serializing_if = "Option::is_none")]
532 pub line: Option<u32>,
533 #[serde(skip_serializing_if = "Option::is_none")]
535 pub limit: Option<u32>,
536 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
538 pub meta: Option<serde_json::Value>,
539}
540
541impl ReadTextFileRequest {
542 pub fn new(session_id: SessionId, path: impl Into<PathBuf>) -> Self {
543 Self {
544 session_id,
545 path: path.into(),
546 line: None,
547 limit: None,
548 meta: None,
549 }
550 }
551
552 #[must_use]
554 pub fn line(mut self, line: u32) -> Self {
555 self.line = Some(line);
556 self
557 }
558
559 #[must_use]
561 pub fn limit(mut self, limit: u32) -> Self {
562 self.limit = Some(limit);
563 self
564 }
565
566 #[must_use]
568 pub fn meta(mut self, meta: serde_json::Value) -> Self {
569 self.meta = Some(meta);
570 self
571 }
572}
573
574#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
576#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
577#[serde(rename_all = "camelCase")]
578#[non_exhaustive]
579pub struct ReadTextFileResponse {
580 pub content: String,
581 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
583 pub meta: Option<serde_json::Value>,
584}
585
586impl ReadTextFileResponse {
587 pub fn new(content: impl Into<String>) -> Self {
588 Self {
589 content: content.into(),
590 meta: None,
591 }
592 }
593
594 #[must_use]
596 pub fn meta(mut self, meta: serde_json::Value) -> Self {
597 self.meta = Some(meta);
598 self
599 }
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
605#[serde(transparent)]
606#[from(Arc<str>, String, &'static str)]
607#[non_exhaustive]
608pub struct TerminalId(pub Arc<str>);
609
610impl TerminalId {
611 pub fn new(id: impl Into<Arc<str>>) -> Self {
612 Self(id.into())
613 }
614}
615
616#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
618#[serde(rename_all = "camelCase")]
619#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
620#[non_exhaustive]
621pub struct CreateTerminalRequest {
622 pub session_id: SessionId,
624 pub command: String,
626 #[serde(default, skip_serializing_if = "Vec::is_empty")]
628 pub args: Vec<String>,
629 #[serde(default, skip_serializing_if = "Vec::is_empty")]
631 pub env: Vec<crate::EnvVariable>,
632 #[serde(skip_serializing_if = "Option::is_none")]
634 pub cwd: Option<PathBuf>,
635 #[serde(skip_serializing_if = "Option::is_none")]
644 pub output_byte_limit: Option<u64>,
645 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
647 pub meta: Option<serde_json::Value>,
648}
649
650impl CreateTerminalRequest {
651 pub fn new(session_id: SessionId, command: impl Into<String>) -> Self {
652 Self {
653 session_id,
654 command: command.into(),
655 args: Vec::new(),
656 env: Vec::new(),
657 cwd: None,
658 output_byte_limit: None,
659 meta: None,
660 }
661 }
662
663 #[must_use]
665 pub fn args(mut self, args: Vec<String>) -> Self {
666 self.args = args;
667 self
668 }
669
670 #[must_use]
672 pub fn env(mut self, env: Vec<crate::EnvVariable>) -> Self {
673 self.env = env;
674 self
675 }
676
677 #[must_use]
679 pub fn cwd(mut self, cwd: impl Into<PathBuf>) -> Self {
680 self.cwd = Some(cwd.into());
681 self
682 }
683
684 #[must_use]
693 pub fn output_byte_limit(mut self, output_byte_limit: u64) -> Self {
694 self.output_byte_limit = Some(output_byte_limit);
695 self
696 }
697
698 #[must_use]
700 pub fn meta(mut self, meta: serde_json::Value) -> Self {
701 self.meta = Some(meta);
702 self
703 }
704}
705
706#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
708#[serde(rename_all = "camelCase")]
709#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
710#[non_exhaustive]
711pub struct CreateTerminalResponse {
712 pub terminal_id: TerminalId,
714 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
716 pub meta: Option<serde_json::Value>,
717}
718
719impl CreateTerminalResponse {
720 #[must_use]
721 pub fn new(terminal_id: TerminalId) -> Self {
722 Self {
723 terminal_id,
724 meta: None,
725 }
726 }
727
728 #[must_use]
730 pub fn meta(mut self, meta: serde_json::Value) -> Self {
731 self.meta = Some(meta);
732 self
733 }
734}
735
736#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
738#[serde(rename_all = "camelCase")]
739#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
740#[non_exhaustive]
741pub struct TerminalOutputRequest {
742 pub session_id: SessionId,
744 pub terminal_id: TerminalId,
746 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
748 pub meta: Option<serde_json::Value>,
749}
750
751impl TerminalOutputRequest {
752 #[must_use]
753 pub fn new(session_id: SessionId, terminal_id: TerminalId) -> Self {
754 Self {
755 session_id,
756 terminal_id,
757 meta: None,
758 }
759 }
760
761 #[must_use]
763 pub fn meta(mut self, meta: serde_json::Value) -> Self {
764 self.meta = Some(meta);
765 self
766 }
767}
768
769#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
771#[serde(rename_all = "camelCase")]
772#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
773#[non_exhaustive]
774pub struct TerminalOutputResponse {
775 pub output: String,
777 pub truncated: bool,
779 pub exit_status: Option<TerminalExitStatus>,
781 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
783 pub meta: Option<serde_json::Value>,
784}
785
786impl TerminalOutputResponse {
787 pub fn new(output: impl Into<String>, truncated: bool) -> Self {
788 Self {
789 output: output.into(),
790 truncated,
791 exit_status: None,
792 meta: None,
793 }
794 }
795
796 #[must_use]
798 pub fn exit_status(mut self, exit_status: TerminalExitStatus) -> Self {
799 self.exit_status = Some(exit_status);
800 self
801 }
802
803 #[must_use]
805 pub fn meta(mut self, meta: serde_json::Value) -> Self {
806 self.meta = Some(meta);
807 self
808 }
809}
810
811#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
813#[serde(rename_all = "camelCase")]
814#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
815#[non_exhaustive]
816pub struct ReleaseTerminalRequest {
817 pub session_id: SessionId,
819 pub terminal_id: TerminalId,
821 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
823 pub meta: Option<serde_json::Value>,
824}
825
826impl ReleaseTerminalRequest {
827 #[must_use]
828 pub fn new(session_id: SessionId, terminal_id: TerminalId) -> Self {
829 Self {
830 session_id,
831 terminal_id,
832 meta: None,
833 }
834 }
835
836 #[must_use]
838 pub fn meta(mut self, meta: serde_json::Value) -> Self {
839 self.meta = Some(meta);
840 self
841 }
842}
843
844#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
846#[serde(rename_all = "camelCase")]
847#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
848#[non_exhaustive]
849pub struct ReleaseTerminalResponse {
850 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
852 pub meta: Option<serde_json::Value>,
853}
854
855impl ReleaseTerminalResponse {
856 #[must_use]
857 pub fn new() -> Self {
858 Self::default()
859 }
860
861 #[must_use]
863 pub fn meta(mut self, meta: serde_json::Value) -> Self {
864 self.meta = Some(meta);
865 self
866 }
867}
868
869#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
871#[serde(rename_all = "camelCase")]
872#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
873#[non_exhaustive]
874pub struct KillTerminalCommandRequest {
875 pub session_id: SessionId,
877 pub terminal_id: TerminalId,
879 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
881 pub meta: Option<serde_json::Value>,
882}
883
884impl KillTerminalCommandRequest {
885 #[must_use]
886 pub fn new(session_id: SessionId, terminal_id: TerminalId) -> Self {
887 Self {
888 session_id,
889 terminal_id,
890 meta: None,
891 }
892 }
893
894 #[must_use]
896 pub fn meta(mut self, meta: serde_json::Value) -> Self {
897 self.meta = Some(meta);
898 self
899 }
900}
901
902#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
904#[serde(rename_all = "camelCase")]
905#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
906#[non_exhaustive]
907pub struct KillTerminalCommandResponse {
908 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
910 pub meta: Option<serde_json::Value>,
911}
912
913impl KillTerminalCommandResponse {
914 #[must_use]
915 pub fn new() -> Self {
916 Self::default()
917 }
918
919 #[must_use]
921 pub fn meta(mut self, meta: serde_json::Value) -> Self {
922 self.meta = Some(meta);
923 self
924 }
925}
926
927#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
929#[serde(rename_all = "camelCase")]
930#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
931#[non_exhaustive]
932pub struct WaitForTerminalExitRequest {
933 pub session_id: SessionId,
935 pub terminal_id: TerminalId,
937 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
939 pub meta: Option<serde_json::Value>,
940}
941
942impl WaitForTerminalExitRequest {
943 #[must_use]
944 pub fn new(session_id: SessionId, terminal_id: TerminalId) -> Self {
945 Self {
946 session_id,
947 terminal_id,
948 meta: None,
949 }
950 }
951
952 #[must_use]
954 pub fn meta(mut self, meta: serde_json::Value) -> Self {
955 self.meta = Some(meta);
956 self
957 }
958}
959
960#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
962#[serde(rename_all = "camelCase")]
963#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
964#[non_exhaustive]
965pub struct WaitForTerminalExitResponse {
966 #[serde(flatten)]
968 pub exit_status: TerminalExitStatus,
969 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
971 pub meta: Option<serde_json::Value>,
972}
973
974impl WaitForTerminalExitResponse {
975 #[must_use]
976 pub fn new(exit_status: TerminalExitStatus) -> Self {
977 Self {
978 exit_status,
979 meta: None,
980 }
981 }
982
983 #[must_use]
985 pub fn meta(mut self, meta: serde_json::Value) -> Self {
986 self.meta = Some(meta);
987 self
988 }
989}
990
991#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
993#[serde(rename_all = "camelCase")]
994#[non_exhaustive]
995pub struct TerminalExitStatus {
996 pub exit_code: Option<u32>,
998 pub signal: Option<String>,
1000 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1002 pub meta: Option<serde_json::Value>,
1003}
1004
1005impl TerminalExitStatus {
1006 #[must_use]
1007 pub fn new() -> Self {
1008 Self::default()
1009 }
1010
1011 #[must_use]
1013 pub fn exit_code(mut self, exit_code: u32) -> Self {
1014 self.exit_code = Some(exit_code);
1015 self
1016 }
1017
1018 #[must_use]
1020 pub fn signal(mut self, signal: impl Into<String>) -> Self {
1021 self.signal = Some(signal.into());
1022 self
1023 }
1024
1025 #[must_use]
1027 pub fn meta(mut self, meta: serde_json::Value) -> Self {
1028 self.meta = Some(meta);
1029 self
1030 }
1031}
1032
1033#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1042#[serde(rename_all = "camelCase")]
1043#[non_exhaustive]
1044pub struct ClientCapabilities {
1045 #[serde(default)]
1048 pub fs: FileSystemCapability,
1049 #[serde(default)]
1051 pub terminal: bool,
1052 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1054 pub meta: Option<serde_json::Value>,
1055}
1056
1057impl ClientCapabilities {
1058 #[must_use]
1059 pub fn new() -> Self {
1060 Self::default()
1061 }
1062
1063 #[must_use]
1066 pub fn fs(mut self, fs: FileSystemCapability) -> Self {
1067 self.fs = fs;
1068 self
1069 }
1070
1071 #[must_use]
1073 pub fn terminal(mut self, terminal: bool) -> Self {
1074 self.terminal = terminal;
1075 self
1076 }
1077
1078 #[must_use]
1080 pub fn meta(mut self, meta: serde_json::Value) -> Self {
1081 self.meta = Some(meta);
1082 self
1083 }
1084}
1085
1086#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1091#[serde(rename_all = "camelCase")]
1092#[non_exhaustive]
1093pub struct FileSystemCapability {
1094 #[serde(default)]
1096 pub read_text_file: bool,
1097 #[serde(default)]
1099 pub write_text_file: bool,
1100 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1102 pub meta: Option<serde_json::Value>,
1103}
1104
1105impl FileSystemCapability {
1106 #[must_use]
1107 pub fn new() -> Self {
1108 Self::default()
1109 }
1110
1111 #[must_use]
1113 pub fn read_text_file(mut self, read_text_file: bool) -> Self {
1114 self.read_text_file = read_text_file;
1115 self
1116 }
1117
1118 #[must_use]
1120 pub fn write_text_file(mut self, write_text_file: bool) -> Self {
1121 self.write_text_file = write_text_file;
1122 self
1123 }
1124
1125 #[must_use]
1127 pub fn meta(mut self, meta: serde_json::Value) -> Self {
1128 self.meta = Some(meta);
1129 self
1130 }
1131}
1132
1133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1139#[non_exhaustive]
1140pub struct ClientMethodNames {
1141 pub session_request_permission: &'static str,
1143 pub session_update: &'static str,
1145 pub fs_write_text_file: &'static str,
1147 pub fs_read_text_file: &'static str,
1149 pub terminal_create: &'static str,
1151 pub terminal_output: &'static str,
1153 pub terminal_release: &'static str,
1155 pub terminal_wait_for_exit: &'static str,
1157 pub terminal_kill: &'static str,
1159}
1160
1161pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
1163 session_update: SESSION_UPDATE_NOTIFICATION,
1164 session_request_permission: SESSION_REQUEST_PERMISSION_METHOD_NAME,
1165 fs_write_text_file: FS_WRITE_TEXT_FILE_METHOD_NAME,
1166 fs_read_text_file: FS_READ_TEXT_FILE_METHOD_NAME,
1167 terminal_create: TERMINAL_CREATE_METHOD_NAME,
1168 terminal_output: TERMINAL_OUTPUT_METHOD_NAME,
1169 terminal_release: TERMINAL_RELEASE_METHOD_NAME,
1170 terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
1171 terminal_kill: TERMINAL_KILL_METHOD_NAME,
1172};
1173
1174pub(crate) const SESSION_UPDATE_NOTIFICATION: &str = "session/update";
1176pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request_permission";
1178pub(crate) const FS_WRITE_TEXT_FILE_METHOD_NAME: &str = "fs/write_text_file";
1180pub(crate) const FS_READ_TEXT_FILE_METHOD_NAME: &str = "fs/read_text_file";
1182pub(crate) const TERMINAL_CREATE_METHOD_NAME: &str = "terminal/create";
1184pub(crate) const TERMINAL_OUTPUT_METHOD_NAME: &str = "terminal/output";
1186pub(crate) const TERMINAL_RELEASE_METHOD_NAME: &str = "terminal/release";
1188pub(crate) const TERMINAL_WAIT_FOR_EXIT_METHOD_NAME: &str = "terminal/wait_for_exit";
1190pub(crate) const TERMINAL_KILL_METHOD_NAME: &str = "terminal/kill";
1192
1193#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1200#[serde(untagged)]
1201#[schemars(extend("x-docs-ignore" = true))]
1202#[non_exhaustive]
1203pub enum AgentRequest {
1204 WriteTextFileRequest(WriteTextFileRequest),
1211 ReadTextFileRequest(ReadTextFileRequest),
1218 RequestPermissionRequest(RequestPermissionRequest),
1229 CreateTerminalRequest(CreateTerminalRequest),
1244 TerminalOutputRequest(TerminalOutputRequest),
1251 ReleaseTerminalRequest(ReleaseTerminalRequest),
1264 WaitForTerminalExitRequest(WaitForTerminalExitRequest),
1268 KillTerminalCommandRequest(KillTerminalCommandRequest),
1281 ExtMethodRequest(ExtRequest),
1289}
1290
1291#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1298#[serde(untagged)]
1299#[schemars(extend("x-docs-ignore" = true))]
1300#[non_exhaustive]
1301pub enum ClientResponse {
1302 WriteTextFileResponse(#[serde(default)] WriteTextFileResponse),
1303 ReadTextFileResponse(ReadTextFileResponse),
1304 RequestPermissionResponse(RequestPermissionResponse),
1305 CreateTerminalResponse(CreateTerminalResponse),
1306 TerminalOutputResponse(TerminalOutputResponse),
1307 ReleaseTerminalResponse(#[serde(default)] ReleaseTerminalResponse),
1308 WaitForTerminalExitResponse(WaitForTerminalExitResponse),
1309 KillTerminalResponse(#[serde(default)] KillTerminalCommandResponse),
1310 ExtMethodResponse(#[schemars(with = "serde_json::Value")] Arc<RawValue>),
1311}
1312
1313#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1320#[serde(untagged)]
1321#[expect(clippy::large_enum_variant)]
1322#[schemars(extend("x-docs-ignore" = true))]
1323#[non_exhaustive]
1324pub enum AgentNotification {
1325 SessionNotification(SessionNotification),
1337 ExtNotification(ExtNotification),
1345}