mi6_core/model/session/query.rs
1//! Session query types and builders.
2//!
3//! This module provides types for querying sessions:
4//! - [`SessionOrder`]: Field to order results by
5//! - [`SessionQuery`]: Fluent builder for constructing queries
6
7use chrono::{DateTime, Utc};
8
9use super::super::Order;
10
11/// Sort order for session queries
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
13pub enum SessionOrder {
14 /// Order by session start time (default: newest first)
15 #[default]
16 StartedAt,
17 /// Order by last activity time
18 LastActivity,
19 /// Order by total cost
20 Cost,
21}
22
23/// Query builder for session retrieval.
24///
25/// `SessionQuery` provides a fluent API for constructing session queries
26/// with filters, ordering, and pagination.
27///
28/// Default ordering is newest first (descending by started_at).
29#[derive(Clone)]
30pub struct SessionQuery {
31 /// Filter by machine_id (for multi-machine scenarios)
32 pub machine_id: Option<String>,
33
34 /// Filter by framework (claude, cursor, gemini, codex)
35 pub framework: Option<String>,
36
37 /// Filter to only active sessions (ended_at IS NULL)
38 pub active_only: bool,
39
40 /// Filter sessions with activity after this timestamp
41 pub active_since: Option<DateTime<Utc>>,
42
43 /// Filter sessions started after this timestamp
44 pub started_after: Option<DateTime<Utc>>,
45
46 /// Filter sessions started before this timestamp
47 pub started_before: Option<DateTime<Utc>>,
48
49 /// Filter by GitHub repository (owner/repo format)
50 pub github_repo: Option<String>,
51
52 /// Filter by GitHub issue number
53 pub github_issue: Option<i32>,
54
55 /// Filter by GitHub PR number
56 pub github_pr: Option<i32>,
57
58 /// Maximum number of sessions to return
59 pub limit: Option<usize>,
60
61 /// Order by field
62 pub order_by: SessionOrder,
63
64 /// Sort direction (default: Desc for newest first)
65 pub direction: Order,
66}
67
68impl Default for SessionQuery {
69 fn default() -> Self {
70 Self {
71 machine_id: None,
72 framework: None,
73 active_only: false,
74 active_since: None,
75 started_after: None,
76 started_before: None,
77 github_repo: None,
78 github_issue: None,
79 github_pr: None,
80 limit: None,
81 order_by: SessionOrder::default(),
82 direction: Order::Desc, // Default to newest first
83 }
84 }
85}
86
87impl SessionQuery {
88 /// Create a new empty query (defaults to recent sessions first)
89 pub fn new() -> Self {
90 Self::default()
91 }
92
93 /// Filter to only active sessions
94 pub fn active_only(mut self) -> Self {
95 self.active_only = true;
96 self
97 }
98
99 /// Filter by machine_id (for multi-machine scenarios)
100 pub fn with_machine_id(mut self, machine_id: impl Into<String>) -> Self {
101 self.machine_id = Some(machine_id.into());
102 self
103 }
104
105 /// Filter by framework
106 pub fn with_framework(mut self, framework: impl Into<String>) -> Self {
107 self.framework = Some(framework.into());
108 self
109 }
110
111 /// Filter sessions with activity since the given timestamp
112 pub fn with_active_since(mut self, ts: DateTime<Utc>) -> Self {
113 self.active_since = Some(ts);
114 self
115 }
116
117 /// Filter sessions started after the given timestamp
118 pub fn with_started_after(mut self, ts: DateTime<Utc>) -> Self {
119 self.started_after = Some(ts);
120 self
121 }
122
123 /// Filter sessions started before the given timestamp
124 pub fn with_started_before(mut self, ts: DateTime<Utc>) -> Self {
125 self.started_before = Some(ts);
126 self
127 }
128
129 /// Filter by GitHub repository (owner/repo format)
130 pub fn with_github_repo(mut self, repo: impl Into<String>) -> Self {
131 self.github_repo = Some(repo.into());
132 self
133 }
134
135 /// Filter by GitHub issue number
136 pub fn with_github_issue(mut self, issue: i32) -> Self {
137 self.github_issue = Some(issue);
138 self
139 }
140
141 /// Filter by GitHub PR number
142 pub fn with_github_pr(mut self, pr: i32) -> Self {
143 self.github_pr = Some(pr);
144 self
145 }
146
147 /// Set the maximum number of sessions to return
148 pub fn with_limit(mut self, limit: usize) -> Self {
149 self.limit = Some(limit);
150 self
151 }
152
153 /// Order by the given field
154 pub fn with_order_by(mut self, order: SessionOrder) -> Self {
155 self.order_by = order;
156 self
157 }
158
159 /// Set the sort direction (Asc/Desc).
160 ///
161 /// This method is consistent with `EventQuery::with_direction()`.
162 pub fn with_direction(mut self, direction: Order) -> Self {
163 self.direction = direction;
164 self
165 }
166
167 /// Set ascending order (convenience method).
168 ///
169 /// Equivalent to `.with_direction(Order::Asc)`.
170 pub fn ascending(self) -> Self {
171 self.with_direction(Order::Asc)
172 }
173
174 /// Set descending order (convenience method).
175 ///
176 /// Equivalent to `.with_direction(Order::Desc)`.
177 pub fn descending(self) -> Self {
178 self.with_direction(Order::Desc)
179 }
180}