1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 ipc::{CliUsageLimitState, ScreenStatus},
6 session::{AdoptedFrom, AgentAttention, PendingResponseCardState, Session, SessionStatus},
7};
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
10pub struct ApiHealth {
11 pub status: String,
12 pub pid: u32,
13 pub started_at: DateTime<Utc>,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
17pub struct DaemonRuntimeState {
18 pub pid: u32,
19 pub api_addr: String,
20 pub started_at: DateTime<Utc>,
21 pub log_path: String,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
25pub struct CreateSessionRequest {
26 pub title: String,
27 pub cli_id: String,
28 pub cli_bin: String,
29 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub cgroup_slice: Option<String>,
31 #[serde(default)]
32 pub cli_args: Vec<String>,
33 pub working_dir: String,
34 #[serde(default)]
35 pub prompt: String,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
39pub struct SessionInputRequest {
40 pub content: String,
41 #[serde(default)]
42 pub raw: bool,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
47pub struct MentionTarget {
48 pub open_id: String,
49 #[serde(default)]
50 pub name: Option<String>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
58pub struct FinalOutputRequest {
59 pub content: String,
60
61 #[serde(default)]
64 pub mentions: Vec<MentionTarget>,
65 #[serde(default)]
67 pub mention_back: bool,
68 #[serde(default)]
70 pub no_mention: bool,
71
72 #[serde(default)]
75 pub files: Vec<String>,
76 #[serde(default)]
78 pub images: Vec<String>,
79
80 #[serde(default)]
83 pub top_level: bool,
84 #[serde(default)]
86 pub chat_id: Option<String>,
87 #[serde(default)]
89 pub into: Option<String>,
90 #[serde(default)]
92 pub quote: Option<String>,
93 #[serde(default)]
95 pub no_quote: bool,
96
97 #[serde(default)]
100 pub voice: bool,
101
102 #[serde(default)]
106 pub attention: Option<String>,
107
108 #[serde(default)]
111 pub card: bool,
112 #[serde(default)]
114 pub text: bool,
115 #[serde(default)]
117 pub anyway: bool,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
121pub struct RestartSessionRequest {
122 #[serde(default)]
123 pub prompt: String,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
127pub struct ResumeSessionRequest {
128 #[serde(default)]
129 pub prompt: String,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
133pub struct AttemptResumeRequest {
134 #[serde(default)]
135 pub reason: Option<String>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
139pub struct AttemptResumeStartResponse {
140 pub ok: bool,
141 pub resume_id: String,
142 pub run_id: String,
143 pub activity_id: String,
144 pub attempt_id: String,
145 pub session_id: String,
146 pub original_session_id: String,
147 #[serde(default, skip_serializing_if = "Option::is_none")]
148 pub cli_session_id: Option<String>,
149 #[serde(default, skip_serializing_if = "Option::is_none")]
150 pub web_port: Option<u16>,
151 #[serde(default, skip_serializing_if = "Option::is_none")]
152 pub write_token: Option<String>,
153 #[serde(default, skip_serializing_if = "Option::is_none")]
154 pub url: Option<String>,
155 pub already_running: bool,
156 pub started_at: u64,
157 pub log_path: String,
158 pub sidecar_path: String,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
162pub struct AttemptResumeEndResponse {
163 pub ok: bool,
164 pub resume_id: String,
165 pub status: String,
166 pub close_reason: String,
167 pub closed_at: u64,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
171pub struct TerminalInfo {
172 pub url: String,
173 #[serde(default, skip_serializing_if = "Option::is_none")]
174 pub read_only_token: Option<String>,
175 #[serde(default, skip_serializing_if = "Option::is_none")]
176 pub write_token: Option<String>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
180pub struct SessionSummary {
181 pub session_id: String,
182 pub title: String,
183 pub status: SessionStatus,
184 pub chat_type: Option<String>,
185 pub quote_target_id: Option<String>,
186 pub cli_id: Option<String>,
187 pub cli_bin: Option<String>,
188 pub cli_args: Vec<String>,
189 pub working_dir: Option<String>,
190 pub worker_pid: Option<u32>,
191 pub terminal_url: Option<String>,
192 #[serde(default, skip_serializing_if = "Option::is_none")]
193 pub read_only_token: Option<String>,
194 #[serde(default, skip_serializing_if = "Option::is_none")]
195 pub write_token: Option<String>,
196 pub created_at: DateTime<Utc>,
197 pub stream_card_nonce: Option<String>,
198 pub current_screen: Option<String>,
199 pub last_screen_status: Option<ScreenStatus>,
200 pub usage_limit: Option<CliUsageLimitState>,
201 pub current_image_key: Option<String>,
202 pub tui_prompt_card_id: Option<String>,
203 pub tui_prompt_options: Vec<crate::ipc::TuiPromptOption>,
204 pub tui_prompt_multi_select: Option<bool>,
205 pub tui_toggled_indices: Vec<usize>,
206 pub pending_response_card_id: Option<String>,
207 pub pending_response_card_state: Option<PendingResponseCardState>,
208 pub last_patched_response_card_id: Option<String>,
209 pub last_final_output_turn_id: Option<String>,
210 pub last_final_output: Option<String>,
211 pub adopted_from: Option<AdoptedFrom>,
212 #[serde(default, skip_serializing_if = "Option::is_none")]
213 pub agent_attention: Option<AgentAttention>,
214 #[serde(default)]
217 pub worker_unresponsive: bool,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
221pub struct BotSummary {
222 pub lark_app_id: String,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub name: Option<String>,
225 pub cli_id: String,
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub model: Option<String>,
228 pub allowed_users: Vec<String>,
229 #[serde(skip_serializing_if = "Vec::is_empty")]
230 pub allowed_chat_groups: Vec<String>,
231 #[serde(skip_serializing_if = "Vec::is_empty")]
232 pub oncall_chats: Vec<String>,
233 pub private_card: bool,
234 pub active_sessions: usize,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
238pub struct SessionGroup {
239 pub chat_id: String,
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub title: Option<String>,
242 pub sessions: Vec<SessionSummary>,
243}
244
245#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
246pub struct DaemonOverview {
247 pub pid: u32,
248 pub started_at: DateTime<Utc>,
249 pub session_count: usize,
250 pub active_session_count: usize,
251 pub closed_session_count: usize,
252 pub bot_count: usize,
253 pub worker_count: usize,
254 pub config_path: String,
255 pub data_dir: String,
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
259pub struct SessionLocateInfo {
260 pub session_id: String,
261 pub terminal_url: Option<String>,
262 pub worker_pid: Option<u32>,
263}
264
265impl From<&Session> for SessionSummary {
266 fn from(value: &Session) -> Self {
267 Self {
268 session_id: value.session_id.clone(),
269 title: value.title.clone(),
270 status: value.status,
271 chat_type: value.chat_type.clone(),
272 quote_target_id: value.quote_target_id.clone(),
273 cli_id: value.cli_id.clone(),
274 cli_bin: value.cli_bin.clone(),
275 cli_args: value.cli_args.clone(),
276 working_dir: value.working_dir.clone(),
277 worker_pid: value.worker_pid,
278 terminal_url: value.terminal_url.clone(),
279 read_only_token: None,
280 write_token: None,
281 created_at: value.created_at,
282 stream_card_nonce: value.stream_card_nonce.clone(),
283 current_screen: value.current_screen.clone(),
284 last_screen_status: value.last_screen_status,
285 usage_limit: value.usage_limit.clone(),
286 current_image_key: value.current_image_key.clone(),
287 tui_prompt_card_id: value.tui_prompt_card_id.clone(),
288 tui_prompt_options: value.tui_prompt_options.clone(),
289 tui_prompt_multi_select: value.tui_prompt_multi_select,
290 tui_toggled_indices: value.tui_toggled_indices.clone(),
291 pending_response_card_id: value.pending_response_card_id.clone(),
292 pending_response_card_state: value.pending_response_card_state,
293 last_patched_response_card_id: value.last_patched_response_card_id.clone(),
294 last_final_output_turn_id: value.last_final_output_turn_id.clone(),
295 last_final_output: value.last_final_output.clone(),
296 adopted_from: value.adopted_from.clone(),
297 agent_attention: value.agent_attention.clone(),
298 worker_unresponsive: false,
299 }
300 }
301}
302
303#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
306pub struct AttentionRequest {
307 #[serde(alias = "sessionId")]
308 pub session_id: String,
309 pub kind: String,
310 pub reason: String,
311}