146 lines
4.1 KiB
Rust
146 lines
4.1 KiB
Rust
use anyhow::{Result, Context};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
/// 会话数据
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
pub struct Session {
|
|
pub messages: Vec<(String, String)>, // (role, content)
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
impl Session {
|
|
/// 创建新会话
|
|
pub fn new() -> Self {
|
|
let now = chrono::Local::now().to_rfc3339();
|
|
Self {
|
|
messages: Vec::new(),
|
|
created_at: now.clone(),
|
|
updated_at: now,
|
|
}
|
|
}
|
|
|
|
/// 添加消息
|
|
pub fn add_message(&mut self, role: String, content: String) {
|
|
self.messages.push((role, content));
|
|
self.updated_at = chrono::Local::now().to_rfc3339();
|
|
}
|
|
|
|
/// 获取消息列表
|
|
pub fn get_messages(&self) -> Vec<(String, String)> {
|
|
self.messages.clone()
|
|
}
|
|
}
|
|
|
|
/// 缓存管理器
|
|
pub struct CacheManager {
|
|
cache_dir: PathBuf,
|
|
}
|
|
|
|
impl CacheManager {
|
|
/// 创建缓存管理器
|
|
pub fn new() -> Result<Self> {
|
|
let cache_dir = PathBuf::from(".cache/sessions");
|
|
|
|
// 创建缓存目录
|
|
if !cache_dir.exists() {
|
|
fs::create_dir_all(&cache_dir)
|
|
.context("创建缓存目录失败")?;
|
|
}
|
|
|
|
Ok(Self { cache_dir })
|
|
}
|
|
|
|
/// 获取最新的会话文件路径
|
|
pub fn get_latest_session_path(&self) -> Option<PathBuf> {
|
|
if !self.cache_dir.exists() {
|
|
return None;
|
|
}
|
|
|
|
let mut entries: Vec<_> = fs::read_dir(&self.cache_dir)
|
|
.ok()?
|
|
.filter_map(|entry| entry.ok())
|
|
.filter(|entry| {
|
|
entry.path().extension()
|
|
.map(|ext| ext == "json")
|
|
.unwrap_or(false)
|
|
})
|
|
.collect();
|
|
|
|
// 按修改时间排序(最新的在前)
|
|
entries.sort_by_key(|entry| {
|
|
entry.metadata()
|
|
.and_then(|m| m.modified())
|
|
.unwrap_or(std::time::SystemTime::UNIX_EPOCH)
|
|
});
|
|
entries.reverse();
|
|
|
|
entries.first().map(|entry| entry.path())
|
|
}
|
|
|
|
/// 创建新的会话文件路径
|
|
pub fn create_session_path(&self) -> PathBuf {
|
|
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S");
|
|
self.cache_dir.join(format!("session_{}.json", timestamp))
|
|
}
|
|
|
|
/// 保存会话
|
|
pub fn save_session(&self, session: &Session, path: &Path) -> Result<()> {
|
|
let json = serde_json::to_string_pretty(session)
|
|
.context("序列化会话失败")?;
|
|
|
|
fs::write(path, json)
|
|
.context("保存会话文件失败")?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 加载会话
|
|
pub fn load_session(&self, path: &Path) -> Result<Session> {
|
|
let json = fs::read_to_string(path)
|
|
.context("读取会话文件失败")?;
|
|
|
|
let session: Session = serde_json::from_str(&json)
|
|
.context("解析会话文件失败")?;
|
|
|
|
Ok(session)
|
|
}
|
|
|
|
/// 获取所有会话文件
|
|
pub fn list_sessions(&self) -> Result<Vec<(String, PathBuf)>> {
|
|
if !self.cache_dir.exists() {
|
|
return Ok(Vec::new());
|
|
}
|
|
|
|
let mut sessions = Vec::new();
|
|
|
|
for entry in fs::read_dir(&self.cache_dir)? {
|
|
let entry = entry?;
|
|
let path = entry.path();
|
|
|
|
if path.extension().map(|ext| ext == "json").unwrap_or(false) {
|
|
if let Ok(metadata) = entry.metadata() {
|
|
if let Ok(modified) = metadata.modified() {
|
|
let datetime = chrono::DateTime::<chrono::Local>::from(modified);
|
|
sessions.push((datetime.format("%Y-%m-%d %H:%M:%S").to_string(), path));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 按时间排序(最新的在前)
|
|
sessions.sort_by(|a, b| b.0.cmp(&a.0));
|
|
|
|
Ok(sessions)
|
|
}
|
|
}
|
|
|
|
// 为Session实现Default trait
|
|
impl Default for Session {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|