1use std::path::PathBuf;
2
3use chrono::{DateTime, Utc};
4
5#[derive(Debug, Clone)]
6pub struct Session {
7 pub id: String,
8 pub provider: String,
9 pub summary: String,
10 pub cwd: String,
11 pub created_at: DateTime<Utc>,
12 pub updated_at: DateTime<Utc>,
13 pub checkpoints: Vec<Checkpoint>,
14 pub user_messages: Vec<String>,
15 pub task_summaries: Vec<String>,
16 pub path: PathBuf,
17}
18
19#[derive(Debug, Clone)]
20pub struct Checkpoint {
21 pub title: String,
22}
23
24pub fn delete_session(session: &Session) -> std::io::Result<()> {
25 if session.path.is_dir() {
26 std::fs::remove_dir_all(&session.path)
27 } else {
28 std::fs::remove_file(&session.path)
29 }
30}
31
32pub fn human_time_ago(dt: &DateTime<Utc>) -> String {
33 let now = Utc::now();
34 let duration = now.signed_duration_since(*dt);
35
36 let minutes = duration.num_minutes();
37 let hours = duration.num_hours();
38 let days = duration.num_days();
39
40 if minutes < 1 {
41 "just now".to_string()
42 } else if minutes < 60 {
43 format!("{minutes}m ago")
44 } else if hours < 24 {
45 format!("{hours}h ago")
46 } else if days < 30 {
47 format!("{days}d ago")
48 } else {
49 dt.format("%b %d, %Y").to_string()
50 }
51}
52
53pub fn truncate(s: &str, max: usize) -> String {
54 if s.chars().count() <= max {
55 s.to_string()
56 } else {
57 let truncated: String = s.chars().take(max).collect();
58 format!("{truncated}…")
59 }
60}