agent_first_mail/cli/cases.rs
1use clap::{Args, Subcommand};
2
3#[derive(Subcommand, Debug)]
4pub enum CaseCommand {
5 /// Create a new case and return its stable UID/ref.
6 Create(CaseCreateArgs),
7 /// List compact active case locators.
8 List,
9 /// Show a case's case.md (active or archived) without changing workspace state.
10 Show {
11 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
12 case_ref: String,
13 },
14 /// Add a message to this existing case.
15 Add {
16 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
17 case_ref: String,
18 /// Message id to add.
19 message_id: String,
20 /// Short summary for this message in the case.
21 #[arg(long)]
22 summary: Option<String>,
23 /// Why this message belongs in this case; required by default.
24 #[arg(long)]
25 reason: Option<String>,
26 },
27 /// Move this case to another group.
28 Move {
29 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
30 case_ref: String,
31 /// Destination group.
32 group: String,
33 },
34 /// Rename this active case's human-readable name without changing its UID.
35 Rename {
36 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
37 case_ref: String,
38 /// New human-readable case name.
39 #[arg(long)]
40 name: String,
41 /// Why this name better represents the case; required by default.
42 #[arg(long)]
43 reason: Option<String>,
44 },
45 /// Show or edit active case notes.
46 Notes {
47 #[command(subcommand)]
48 action: CaseNotesAction,
49 },
50 /// Archive this active case.
51 Archive {
52 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
53 case_ref: String,
54 /// Why this case is ready to archive; required by default.
55 #[arg(long)]
56 reason: Option<String>,
57 },
58 /// Reopen this case as active work without changing its tags.
59 Reopen {
60 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
61 case_ref: String,
62 /// Why this case should be reopened; required by default.
63 #[arg(long)]
64 reason: Option<String>,
65 },
66 /// Add a case organization tag.
67 Tag {
68 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
69 case_ref: String,
70 /// Case organization tag.
71 tag: String,
72 /// Why this tag is useful; required by default.
73 #[arg(long)]
74 reason: Option<String>,
75 },
76 /// Remove a case organization tag.
77 Untag {
78 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
79 case_ref: String,
80 /// Case organization tag.
81 tag: String,
82 /// Why this tag should be removed; required by default.
83 #[arg(long)]
84 reason: Option<String>,
85 },
86 /// Create, edit, validate, queue, or remove local case drafts.
87 Draft {
88 #[command(subcommand)]
89 action: CaseDraftAction,
90 },
91 /// Merge another case into this case.
92 Merge {
93 /// Primary case ref.
94 case_ref: String,
95 /// Case ref to merge into the primary case.
96 other_case_ref: String,
97 /// Why these cases should be merged; required by default.
98 #[arg(long)]
99 reason: Option<String>,
100 },
101}
102
103#[derive(Args, Debug, Clone)]
104pub struct CaseCreateArgs {
105 /// Human-readable case name used in case.md and the directory suffix.
106 #[arg(long)]
107 pub name: String,
108 /// Destination group. Defaults to the configured default group.
109 #[arg(long)]
110 pub group: Option<String>,
111 /// Optional first message to add to the case.
112 #[arg(long)]
113 pub message: Option<String>,
114 /// Short summary for the first message.
115 #[arg(long)]
116 pub summary: Option<String>,
117 /// Why this case is being created.
118 #[arg(long)]
119 pub reason: Option<String>,
120}
121
122#[derive(Subcommand, Debug)]
123pub enum CaseNotesAction {
124 /// Show notes markdown.
125 Show {
126 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
127 case_ref: String,
128 },
129 /// Append text to notes markdown.
130 Append {
131 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
132 case_ref: String,
133 /// Markdown text to append.
134 #[arg(long)]
135 text: String,
136 },
137 /// Replace notes markdown with text.
138 Replace {
139 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
140 case_ref: String,
141 /// Markdown text to write.
142 #[arg(long)]
143 text: String,
144 },
145}
146
147#[derive(Subcommand, Debug)]
148pub enum CaseDraftAction {
149 /// Scaffold a new outbound draft (not a reply) in this case.
150 New {
151 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
152 case_ref: String,
153 /// Recipient address. Repeatable.
154 #[arg(long = "to", required = true)]
155 to: Vec<String>,
156 /// Cc address. Repeatable.
157 #[arg(long = "cc")]
158 cc: Vec<String>,
159 /// Draft subject.
160 #[arg(long)]
161 subject: String,
162 /// Draft body text.
163 #[arg(long, conflicts_with = "body_file")]
164 body: Option<String>,
165 /// Path to a file whose contents become the draft body.
166 #[arg(long = "body-file")]
167 body_file: Option<String>,
168 },
169 /// Scaffold a reply draft to a message, prefilled and quoting the original.
170 Reply {
171 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
172 case_ref: String,
173 /// Message id in this case to reply to.
174 message_id: String,
175 /// Draft body text. Replaces the default reply template when provided.
176 #[arg(long, conflicts_with = "body_file")]
177 body: Option<String>,
178 /// Path to a file whose contents become the draft body.
179 #[arg(long = "body-file")]
180 body_file: Option<String>,
181 /// Reply to all original recipients (To and Cc), not just the sender.
182 #[arg(long)]
183 all: bool,
184 },
185 /// Change an existing editable draft in place.
186 Change {
187 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
188 case_ref: String,
189 /// Draft markdown file under the case drafts directory.
190 draft_name: String,
191 /// Replacement subject.
192 #[arg(long)]
193 subject: Option<String>,
194 /// Replacement To list. Repeatable; when provided it replaces all To recipients.
195 #[arg(long = "to")]
196 to: Vec<String>,
197 /// Replacement Cc list. Repeatable; when provided it replaces all Cc recipients.
198 #[arg(long = "cc", conflicts_with = "clear_cc")]
199 cc: Vec<String>,
200 /// Clear all Cc recipients.
201 #[arg(long)]
202 clear_cc: bool,
203 /// Replacement draft body text.
204 #[arg(long, conflicts_with = "body_file")]
205 body: Option<String>,
206 /// Path to a file whose contents replace the draft body.
207 #[arg(long = "body-file")]
208 body_file: Option<String>,
209 },
210 /// Show an existing draft in a review-friendly JSON shape.
211 Show {
212 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
213 case_ref: String,
214 /// Draft markdown file under the case drafts directory.
215 draft_name: String,
216 },
217 /// Validate a draft under the case drafts directory.
218 Validate {
219 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
220 case_ref: String,
221 /// Draft markdown file under the case drafts directory.
222 draft_name: String,
223 },
224 /// Queue this draft to be saved to the remote Drafts mailbox.
225 Save {
226 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
227 case_ref: String,
228 /// Draft markdown file under the case drafts directory.
229 draft_name: String,
230 },
231 /// Queue this draft to be sent and recorded in the case after push succeeds.
232 Send {
233 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
234 case_ref: String,
235 /// Draft markdown file under the case drafts directory.
236 draft_name: String,
237 },
238 /// Copy or reference a file and add it to a draft's attachments.
239 Attach {
240 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
241 case_ref: String,
242 /// Draft markdown file under the case drafts directory.
243 draft_name: String,
244 /// Local file path to attach.
245 path: String,
246 },
247 /// Remove a local draft and any queued outbound item for it.
248 Remove {
249 /// Case ref: cYYYYMMDDNNN or cYYYYMMDDNNN-any-suffix.
250 case_ref: String,
251 /// Draft markdown file under the case drafts directory.
252 draft_name: String,
253 /// Why this draft should be removed; required by default.
254 #[arg(long)]
255 reason: Option<String>,
256 },
257}