tycode_core/persistence/
session.rs1use std::collections::HashMap;
2use std::path::PathBuf;
3
4use chrono::Utc;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8use crate::ai::types::{Message, MessageRole};
9use crate::chat::events::ChatEvent;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SessionData {
13 pub id: String,
14 pub created_at: u64,
15 pub last_modified: u64,
16 pub messages: Vec<Message>,
17 pub tracked_files: Vec<PathBuf>,
18 pub events: Vec<ChatEvent>,
19
20 #[serde(flatten)]
24 pub module_state: HashMap<String, Value>,
25}
26
27impl SessionData {
28 pub fn new(id: String, messages: Vec<Message>, tracked_files: Vec<PathBuf>) -> Self {
29 let now = Utc::now().timestamp_millis() as u64;
30 Self {
31 id,
32 created_at: now,
33 last_modified: now,
34 messages,
35 tracked_files,
36 events: Vec::new(),
37 module_state: HashMap::new(),
38 }
39 }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct SessionMetadata {
44 pub id: String,
45 pub title: String,
46 pub last_modified: u64,
47}
48
49impl SessionMetadata {
50 pub fn from_session_data(data: &SessionData) -> Self {
51 let title = data
52 .messages
53 .iter()
54 .find(|msg| msg.role == MessageRole::User)
55 .map(|msg| Self::truncate_text(&msg.content.text()))
56 .unwrap_or_else(|| "New Session".to_string());
57
58 Self {
59 id: data.id.clone(),
60 title,
61 last_modified: data.last_modified,
62 }
63 }
64
65 fn truncate_text(text: &str) -> String {
66 let truncated: String = text.chars().take(50).collect();
67 if text.chars().count() > 50 {
68 format!("{}...", truncated)
69 } else {
70 truncated
71 }
72 }
73}