Skip to main content

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}